Update versions.
Jeanphi
2 # -*- coding: utf-8 -*-
4 """Registration info for Blender menus:
5 Name: 'LuxBlend v0.7 Exporter'
8 Tooltip: 'Export/Render to LuxRender v0.7 scene format (.lxs)'
11 __author__ = "radiance, zuegs, ideasman42, luxblender, dougal2, SATtva"
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.7 exporter
38 # --------------------------------------------------------------------------
41 # radiance, zuegs, ideasman42, luxblender, dougal2, SATtva
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, Modifier, Texture, Window, sys, Draw, BGL, Mathutils, Lamp, Image, Particle, Curve
76 # critical export function profiling
78 import hotshot, hotshot.stats
79 def profileit(printlines=1):
81 def _func(*args, **kargs):
82 prof = hotshot.Profile("profiling.data")
83 res = prof.runcall(func, *args, **kargs)
85 stats = hotshot.stats.load("profiling.data")
87 stats.sort_stats('time', 'calls')
88 print ">>>---- Begin profiling print for %s" % func.__name__
89 stats.print_stats(printlines)
90 print ">>>---- End profiling print"
95 def profileit(arg=None):
101 ######################################################
103 ######################################################
105 # New name based on old with a different extension
107 return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext
112 return str.replace("\\", "\\\\")
115 ### relpath ##########################
116 def relpath(base, target):
117 if target[0:2] == "\\\\" or target[0:2] == "//":
118 return target[2:len(target)]
119 if not os.path.isabs(base):
120 base = os.path.abspath(base)
121 if not os.path.isabs(target):
122 target = os.path.abspath(target)
124 base = os.path.normcase(base)
125 target = os.path.normcase(target)
128 baselist = base.split(os.sep)
129 if baselist[-1] == "":
130 baselist = baselist[:-1]
131 targetlist = target.split(os.sep)
133 top = min([len(baselist), len(targetlist)])
134 while i < top and baselist[i] == targetlist[i]:
137 return os.sep.join(targetlist)
138 if i == len(baselist):
139 return os.sep.join(targetlist[i:])
141 return ('..' + os.sep) * (len(baselist) - i) + os.sep.join(targetlist[i:])
143 ### luxFilePath #####################
146 def luxFilePath(filename):
147 global lxs_filename, previewing
148 scn = Scene.GetCurrent()
149 pm = luxProp(scn, "pathmode", "absolute").get()
150 if (pm=="absolute") or previewing: # absolute paths (the old / default mode)
152 elif pm=="relative": # relative paths
153 base = os.path.dirname(lxs_filename)
154 return relpath(base, filename)
155 elif pm=="flat": # flat mode - only filename
156 return os.path.basename(filename)
160 ###### RGC ##########################
162 scn = Scene.GetCurrent()
163 if luxProp(scn, "RGC", "true").get()=="true":
164 gamma = luxProp(scn, "film.gamma", 2.2).get()
168 if luxProp(scn, "colorclamp", "false").get()=="true":
177 scn = Scene.GetCurrent()
178 if luxProp(scn, "RGC", "true").get()=="true":
179 return luxProp(scn, "film.gamma", 2.2).get()
183 def exportMaterial(mat):
184 str = "# Material '%s'\n" %mat.name
185 return str+luxMaterial(mat)+"\n"
188 def exportMaterialGeomTag(mat):
189 return "%s\n"%(luxProp(mat, "link", "").get())
192 # generate and attach a permanent UID to the scene if there isn't any
195 guid = luxProp(scn, 'UID', '')
197 if (not Blender.Get('filename') and not luxUID) or not g:
198 print 'Lux scene UID is missing. Generating a new one...'
210 except NotImplementedError:
212 r = str(random.getrandbits(160))
213 g = h(str(sys.time())+'|'+r)
214 try: g = g.hexdigest()
215 except: g = hex(g)[2:]
216 print 'Generated UID:', g, "\n"
221 def bitmask(n, max=20):
223 for i in range(max-1, -1, -1):
233 ################################################################
236 dummyMat = 2394723948 # random identifier for dummy material
239 #-------------------------------------------------
241 # helper function to get the material list of an object in respect of obj.colbits
242 #-------------------------------------------------
243 def getMaterials(obj, compress=False):
244 if not obj.type in ['Mesh', 'Curve', 'Surf', 'Text', 'MBall']:
249 colbits = obj.colbits
250 objMats = obj.getMaterials(1)
251 data = obj.getData(mesh=1)
253 dataMats = data.materials
256 dataMats = data.getMaterials(1)
259 dataMats = Curve.Get(obj.getData().getName()).getMaterials()
263 m = max(len(objMats), len(dataMats))
265 objMats.extend([None]*16)
266 dataMats.extend([None]*16)
268 if (colbits & (1<<i) > 0):
271 mats[i] = dataMats[i]
273 mats = [m for m in mats if m]
275 slots = [m for m in mats if m]
276 if m==0 or not slots:
277 print("Warning: object %s has no material assigned" % (obj.getName()))
280 if luxProp(Scene.GetCurrent(), "clay", "false").get()=="true":
282 clayMat = Material.New("lux_clayMat")
284 # resetting clay material to diffuse 0.6
285 luxProp(clayMat, 'type', '').set('matte')
286 luxProp(clayMat, ':Kd', '').set(' '.join([str(rg(0.6))]*3))
287 for i in range(len(mats)):
289 mattype = luxProp(mats[i], "type", "").get()
290 if (mattype not in ["portal","light","boundvolume"]): mats[i] = clayMat
291 if not mats and clayMat is not None: mats.append(clayMat)
295 #-------------------------------------------------
297 # returns modifiers stack and modifiers settings of an object
298 # (modifier rendering parameter is honored)
299 #-------------------------------------------------
300 def getModifiers(obj):
303 for mod in obj.modifiers:
304 if not mod[Modifier.Settings.RENDER]: continue
305 for k in Modifier.Settings.keys():
307 v = mod[getattr(Modifier.Settings, k)]
308 s.append(k+'='+str(v))
311 stack.append([mod.type, s])
312 return str(stack) if len(stack) else ''
315 ######################################################
317 ######################################################
320 #-------------------------------------------------
322 # initializes the exporter object
323 #-------------------------------------------------
324 def __init__(self, scene, master_progress):
326 self.camera = scene.objects.camera
330 self.namedVolumes = []
331 self.hair = {'obj':{}, 'motion':{}}
333 self.instances = {} # only for instances with quirks: redefined materials and modifiers
338 self.mpb = master_progress
340 #-------------------------------------------------
341 # analyseObject(self, obj, matrix, name)
342 # called by analyseScene to build the lists before export
343 #-------------------------------------------------
344 def analyseObject(self, obj, matrix, name, isOriginal=True, isDupli=False):
346 export_emitter = False
347 export_emitter_mats = False
349 obj_type = obj.getType()
351 psystems = obj.getParticleSystems()
352 for psys in psystems:
353 if ( (psys.type == Particle.TYPE['EMITTER'] or psys.type == Particle.TYPE['REACTOR']) and psys.drawAs == Particle.DRAWAS['OBJECT']):
354 if psys.renderEmitter: export_emitter = True
355 dup_obj = psys.duplicateObject
356 self.duplis.add(dup_obj)
358 obj_matrix = dup_obj.getMatrix()
359 obj_translation_vec = obj_matrix.translationPart()
360 obj_rotation_scale_mat = obj_matrix.rotationPart() # This gets a 3D submatrix with the rotation AND scale parts.
363 scales = psys.getSize()
365 if(len(locs) != len(scales) or len(locs) != len(rots)):
366 print("ERROR: Please bake particle systems before rendering")
367 Draw.PupMenu("ERROR: Please bake particle systems before rendering%t|OK%x1")
370 for i in range(len(locs)) :
371 part_rotation_quat = Mathutils.Quaternion(rots[i])
372 part_rotation_mat = part_rotation_quat.toMatrix()
373 rotation_scale_mat = obj_rotation_scale_mat * part_rotation_mat * scales[i]
375 # If dup_obj is translated, the particles are translated by the same amount but
376 # the direction is rotated by the particle rotation. If dup_obj is rotated, that rotation
377 # does not affect the translation. I know it's a bit odd, but that's the way Blender does it
378 # and so that's why the order of the matrix multiplications is like this.
379 translation_vec = Mathutils.Vector(locs[i]) + part_rotation_quat*obj_translation_vec
380 translation_mat = Mathutils.TranslationMatrix(translation_vec)
382 rotation_scale_mat.resize4x4()
384 # Translation must be last because of the way the rotations and translations are encoded in 4D matrices.
385 #combined_matrix = scale_matrix*rotation_mat*translation_mat
386 combined_matrix = rotation_scale_mat*translation_mat
387 #print "combined_matrix = ", combined_matrix
388 self.analyseObject(dup_obj, combined_matrix, "%s.%s"%(obj.getName(), dup_obj.getName()), False, True)
389 #if self.analyseObject(dup_obj, combined_matrix, "%s.%s"%(obj.getName(), dup_obj.getName()), True, True): light = True
390 elif psys.type == Particle.TYPE['HAIR'] and psys.drawAs == Particle.DRAWAS['PATH']:
391 if psys.renderEmitter: export_emitter = True
392 if not obj in self.hair['obj']: self.hair['obj'][obj] = []
394 if not psys.getName() in self.hair['obj'][obj]: self.hair['obj'][obj].append(psys.getName())
395 except AttributeError:
396 print 'ERROR: Installed version of Blender does not properly supports hair particles'
397 print ' export. Please use this version of LuxBlend with Blender 2.49b only.'
398 if osys.platform == 'win32':
399 print ' Important note for users of Blender 2.49b on Windows systems: if you'
400 print ' received this message, then you\'re using an inappropriate build of'
401 print ' Blender program. You can find the correct version build in blender.org'
402 print ' download section in a *zip archive* (not in an installer!).'
404 Draw.PupMenu('ERROR: Blender version does not properly supports hair export (see console for details)%t|OK%x1')
406 if not psys.renderEmitter:
407 export_emitter_mats = True
408 elif psys.drawAs == Particle.DRAWAS['GROUP']:
409 grpObjs = obj.DupObjects
410 grpObjName = obj.name
414 # Prefix the name of all particle objects with "luxGroupParticle".
415 self.analyseObject(o, m, "%s.%s"%("luxGroupParticle", grpObjName), False, True)
417 print "Unknown particle type for particle system [" + obj.name + "]."
419 if (obj.enableDupFrames and isOriginal):
420 for o, m in obj.DupObjects:
421 light = self.analyseObject(o, m, "%s.%s"%(name, o.getName()), False)
422 if (obj.enableDupGroup or obj.enableDupVerts or obj.enableDupFaces):
424 for o, m in obj.DupObjects:
425 if not o.restrictRender and not isDupli:
426 if obj.enableDupGroup:
428 for g in Blender.Group.Get():
429 if o in g.objects: objGroups.append(g)
430 if not objGroups or not True in [ l in o.layers for l in self.groups[g] for g in objGroups ]:
432 light = self.analyseObject(o, m, "%s.%s"%(name, o.getName()), True, True)
433 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"))):
434 if (len(psystems) == 0) or export_emitter or export_emitter_mats:
435 mats = getMaterials(obj)
436 if (len(mats)>0) and (mats[0]!=None) and ((mats[0].name=="PORTAL") or (luxProp(mats[0], "type", "").get()=="portal")):
437 self.portals.append([obj, matrix])
438 elif (len(mats)>0) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
439 self.volumes.append([obj, matrix])
442 if (mat!=None) and (mat not in self.materials):
443 self.materials.append(mat)
444 # collect used named volumes ids
445 for volume_prop in ['Exterior', 'Interior']:
446 if luxProp(mat, '%s_vol_used'%(volume_prop), 'false').get() == 'true':
447 volumeId = luxProp(mat, '%s_vol_id' % (volume_prop), 0).get()
448 if volumeId not in self.namedVolumes:
449 self.namedVolumes.append(volumeId)
450 if (mat!=None) and ((luxProp(mat, "type", "").get()=="light") or (luxProp(mat, "emission", "false").get()=="true")) \
451 and luxProp(Scene.GetCurrent(), "lightgroup.disable."+luxProp(mat, "light.lightgroup", "default").get(), "false").get() != "true":
453 if len(psystems) == 0 or export_emitter:
454 mesh_name = obj.getData(name_only=True)
456 self.meshes[mesh_name] += [obj]
458 self.meshes[mesh_name] = [obj]
459 self.objects.append([obj, matrix])
460 elif (obj_type == "Lamp"):
461 ltype = obj.getData(mesh=1).getType() # data
462 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
463 if luxProp(Scene.GetCurrent(), "lightgroup.disable."+luxProp(obj, "light.lightgroup", "default").get(), "false").get() != "true":
464 self.lights.append([obj, matrix])
468 #-------------------------------------------------
470 # this function builds the lists of object, lights, meshes and materials before export
471 #-------------------------------------------------
472 def analyseScene(self):
474 for g in Blender.Group.Get():
475 # caching groups layers
476 self.groups[g] = bitmask(g.layers)
477 for obj in self.scene.objects:
478 if ((obj.Layers & self.scene.Layers) > 0) and not obj.restrictRender:
479 if self.analyseObject(obj, obj.getMatrix(), obj.getName()): light = True
482 #-------------------------------------------------
483 # exportInstanceObjName(self, mesh_name, matId, shapeId)
484 # format instanced material-separated mesh name
485 #-------------------------------------------------
486 def exportInstanceObjName(self, mesh_name, matId=None, shapeId=None):
488 if matId is None and shapeId is None:
490 s += ':luxInstancedObj'
491 if matId is not None: s += ':matId%s' % matId
492 if shapeId is not None: s += ':shapeId%s' % shapeId
495 #-------------------------------------------------
496 # exportMaterialLink(self, file, mat)
497 # exports material link. LuxRender "Material"
498 #-------------------------------------------------
499 def exportMaterialLink(self, file, mat):
501 file.write("\tMaterial \"matte\" # dummy material\n")
503 file.write("\t%s"%exportMaterialGeomTag(mat)) # use original methode
505 #-------------------------------------------------
506 # exportMaterial(self, file, mat)
507 # exports material. LuxRender "Texture"
508 #-------------------------------------------------
509 def exportMaterial(self, file, mat):
510 #print("material %s"%(mat.getName()))
511 file.write("\t%s"%exportMaterial(mat)) # use original methode
513 #-------------------------------------------------
514 # exportMaterials(self, file)
515 # exports materials to the file
516 #-------------------------------------------------
517 def exportMaterials(self, file):
518 #pb = exportProgressBar(len(self.materials), self.mpb)
519 for mat in self.materials:
520 #pb.counter('Exporting Materials')
521 self.exportMaterial(file, mat)
523 #-------------------------------------------------
524 # exportNamedVolumes(self, file)
525 # exports named volumes to the file
526 #-------------------------------------------------
527 def exportNamedVolumes(self, file):
528 #pb = exportProgressBar(len(self.namedVolumes), self.mpb)
530 volumes = listNamedVolumes()
531 for linked, new in importedVolumeIdsTranslation.items():
532 if linked in self.namedVolumes:
533 self.namedVolumes.remove(linked)
534 self.namedVolumes.append(new)
535 for volume in volumes.values():
536 if volume in self.namedVolumes:
537 #pb.counter('Exporting Mediums Definitions')
538 data = getNamedVolume(volume)
539 output = "\t# Volume '%s'\n" % data['name']
540 tex = luxNamedVolumeTexture(volume)
541 output += "%s\nMakeNamedVolume \"%s\" %s" % (tex[0], data['name'], tex[1])
545 #-------------------------------------------------
546 # exportHairSystems(self, file)
547 # collects hair particles and exports hair systems
548 # primitives to the file
549 #-------------------------------------------------
550 def exportHairSystems(self, file):
551 #pb = exportProgressBar(len(self.hair), self.mpb)
552 clay_export = (luxProp(self.scene, 'clay', 'false').get() != 'true')
553 ob_moblur = (luxProp(self.camera.data, 'objectmblur', 'true').get() == 'true' and luxProp(self.camera.data, 'usemblur', 'false').get() == 'true')
554 frame = Blender.Get('curframe')
555 for obj, obj_psystems in self.hair['obj'].items():
556 #pb.counter('Exporting Hair Particles')
557 for psys in obj.getParticleSystems():
558 psysname = psys.getName()
559 if not psysname in obj_psystems: continue
562 mat = psys.getMat() or dummyMat
564 mat = getMaterials(obj, True)[0]
566 size = luxProp(mat, 'hair_thickness', 0.5).get() * luxScaleUnits('hair_thickness', 'mm', mat)
567 legname = '%s:%s:luxHairPrimitive:leg' % (obj.name, psysname)
568 jointname = '%s:%s:luxHairPrimitive:joint' % (obj.name, psysname)
570 legname: "\tShape \"cylinder\" \"float radius\" %f \"float zmin\" 0.0 \"float zmax\" 1.0\n" % (0.5*size),
571 jointname: "\tShape \"sphere\" \"float radius\" %f\n" % (0.5*size)
573 # exporting primitive objects
574 for name, shape in primitives.items():
575 file.write("ObjectBegin \"%s\"\n" % name)
576 self.exportMaterialLink(file, mat)
578 file.write("ObjectEnd # %s\n\n" % name)
579 # collecting segment objects (instanced)
580 self.luxCollectHairObjs(psys, jointname, legname, size)
582 # to make motion blur work we must also get transform matrices from the following frame
583 Blender.Set('curframe', frame+1)
584 self.luxCollectHairObjs(psys, jointname, legname, size, True)
585 Blender.Set('curframe', frame)
586 # removing psys from the list to avoid multiple exports
587 self.hair['obj'][obj].remove(psysname)
589 # collect hair strand segment objects/matrices pairs
590 def luxCollectHairObjs(self, psys, jointname, legname, size, motion=False):
591 # matrix check helper function
593 for i in range(len(m)):
595 if type(v) is not float and matrixHasNaN(v): return True
596 elif str(v) == 'nan': return True
598 # it seams to be a bug in Blender Python API here -- if an object
599 # has more than one particle system, then beginning from the
600 # second system the call to Particles.getLoc() results in an empty
601 # list for the first time
602 segmentsLoc = psys.getLoc()
603 segmentsLoc = psys.getLoc() # sic
604 for i, strand in enumerate(segmentsLoc):
605 for j in range(0, len(strand)*2-1):
609 matrix = Mathutils.Matrix([1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [strand[j_over_2][0], strand[j_over_2][1], strand[j_over_2][2], 1.0])
612 m = self.getHairSegmentTransform(strand[j_over_2], strand[j_over_2+1])
613 matrix = Mathutils.Matrix(m[0], m[1], m[2], m[3])
614 # check to cull out point-sized strands
615 if j == 1 and not motion and matrixHasNaN(matrix[:3]) is True:
618 obj = self.luxHair('%s_strand%s_segment%s' % (name,i,j), name)
620 self.objects.append([obj, matrix])
622 self.instances[name]['obj_mods'][''] = ['luxHair']
624 self.instances[name] = {'obj_mods': {'': ['luxHair']}}
626 self.hair['motion'][obj] = matrix
628 # minimalistic Blender-like object for holding strand obj properties
630 def __init__(self, objName, parentName):
631 self.objName = objName
632 self.parentName = parentName
633 def __cmp__(self, other):
634 return cmp(self.__repr__(), other.__repr__())
636 return hash(self.__repr__())
638 return '[Object "%s"]' % self.objName
640 return self.__repr__()
641 def getData(self, **args):
642 return self.parentName
646 # hair export helper function (by e_jackson)
647 def getHairSegmentTransform(self, p1, p2):
649 This function selects an orthogonal basis V_1 = (p2-p1), V_2, V_3 such that V_2 and V_3
650 have unit length and calculates a transformation matrix from standard orthnormal basis
653 p1, p2 == coordinate triples of beginning and end points of a vector
655 string which represents transformation matrix in a format compatible with Luxrender SDL
657 # standard orthonormal basis
658 Standard_basis = [Mathutils.Vector(1.0, 0.0, 0.0), Mathutils.Vector(0.0, 1.0, 0.0), Mathutils.Vector(0.0, 0.0, 1.0)]
661 V[2] = Mathutils.Vector(p2) - Mathutils.Vector(p1)
662 # we choose an ort which corresponds to the smallest absolute value of coordinate in V[0]
663 W = Standard_basis[0]
665 for Node in zip([1, 2], [abs(V[2].y), abs(V[2].z)]) :
666 if Node[1] < Length :
668 W = Standard_basis[Node[0]]
671 V[0] = V[1].cross(V[2])
673 # transition matrix from standard basis to V
674 M = Mathutils.Matrix(V[0], V[1], V[2])
676 for Count in range(3) :
677 Result.append([M[Count][0], M[Count][1], M[Count][2], 0.0])
678 Result.append([p1[0], p1[1], p1[2], 1.0])
681 #-------------------------------------------------
682 # getMeshType(self, vertcount, mat, instancedMats)
683 # returns type of mesh as string to use depending on thresholds
684 #-------------------------------------------------
685 def getMeshType(self, vertcount, mat, instancedMats=None):
686 scn = Scene.GetCurrent()
687 if mat != dummyMat and not instancedMats:
688 usesubdiv = luxProp(mat, "subdiv", "false")
689 usedisp = luxProp(mat, "dispmap", "false")
690 sharpbound = luxProp(mat, "sharpbound", "false")
691 nsmooth = luxProp(mat, "nsmooth", "true")
692 sdoffset = luxProp(mat, "sdoffset", 0.0)
694 if usesubdiv.get() == "true":
695 nlevels = luxProp(mat, "sublevels", 1)
696 dstr += "\"loopsubdiv\" \"integer nlevels\" [%i] \"bool dmnormalsmooth\" [\"%s\"] \"bool dmsharpboundary\" [\"%s\"]"% (nlevels.get(), nsmooth.get(), sharpbound.get())
698 if usedisp.get() == "true":
699 dstr += " \"string displacementmap\" [\"%s::dispmap.scale\"] \"float dmscale\" [-1.0] \"float dmoffset\" [%f]"%(mat.getName(), sdoffset.get()) # scale is scaled in texture
701 if dstr != "": return dstr
703 return "\"trianglemesh\""
705 #-------------------------------------------------
706 # exportMesh(self, file, mesh, mats, name, portal, instancedMats, instancedShapes)
707 # exports mesh to the file without any optimization
708 #-------------------------------------------------
709 def exportMesh(self, file, mesh, mats, name, portal=False, instancedMats=None, instancedShapes=None):
710 #print(" exporting mesh")
713 usedmats = [f.mat for f in mesh.faces]
715 for matIndex in range(len(mats)):
716 if not matIndex in usedmats:
723 file.write("ObjectBegin \"%s\"\n" % self.exportInstanceObjName(instancedMats, i, instancedShapes))
724 self.exportMaterialLink(file, mat)
725 mesh_str = self.getMeshType(len(mesh.verts), mats[matIndex], instancedMats)
727 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
729 self.exportMaterialLink(file, mats[matIndex])
730 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
732 ffaces = [f for f in mesh.faces if f.mat == matIndex]
734 file.write("%d %d %d\n"%(index, index+1, index+2))
736 file.write("%d %d %d\n"%(index, index+2, index+3))
737 index += len(face.verts)
738 file.write("\t] \"point P\" [\n")
741 file.write("%f %f %f\n"% tuple(vertex.co))
742 file.write("\t] \"normal N\" [\n")
748 file.write("%f %f %f\n"% tuple(normal))
750 file.write("\t] \"float uv\" [\n")
751 # Check if there is a render specific UV layer and make it active for export.
752 activeUVLayer_orig = mesh.activeUVLayer
753 renderUVLayer = mesh.renderUVLayer
754 if renderUVLayer != activeUVLayer_orig:
755 mesh.activeUVLayer = renderUVLayer
758 file.write("%f %f\n"% tuple(uv))
759 # If we changed the active UV layer: reset it to the original.
760 if renderUVLayer != activeUVLayer_orig:
761 mesh.activeUVLayer = activeUVLayer_orig
764 file.write("ObjectEnd # %s\n\n" % self.exportInstanceObjName(instancedMats, i, instancedShapes))
767 #-------------------------------------------------
768 # exportMeshOpt(self, file, mesh, mats, name, portal, optNormals, instancedMats, instancedShapes)
769 # exports mesh to the file with optimization.
770 # portal: export without normals and UVs
771 # optNormals: speed and filesize optimization, flat faces get exported without normals
772 #-------------------------------------------------
773 def exportMeshOpt(self, file, mesh, mats, name, portal=False, optNormals=True, instancedMats=None, instancedShapes=None):
774 #print(" exporting optimized mesh")
775 shapeList, smoothFltr, shapeText = [0], [[0,1]], [""]
777 normalFltr, uvFltr, shapeText = [0], [0], ["portal"] # portal, no normals, no UVs
779 uvFltr, normalFltr, shapeText = [1], [1], ["mixed with normals"] # normals and UVs
780 if optNormals: # one pass for flat faces without normals and another pass for smoothed faces with normals, all with UVs
781 shapeList, smoothFltr, normalFltr, uvFltr, shapeText = [0,1], [[0],[1]], [0,1], [1,1], ["flat w/o normals", "smoothed with normals"]
784 usedmats = [f.mat for f in mesh.faces]
786 # Check if there is a render specific UV layer and make it active for export.
787 activeUVLayer_orig = mesh.activeUVLayer
788 renderUVLayer = mesh.renderUVLayer
789 if renderUVLayer != activeUVLayer_orig:
790 mesh.activeUVLayer = renderUVLayer
791 for matIndex in range(len(mats)):
792 if not matIndex in usedmats:
799 file.write("ObjectBegin \"%s\"\n" % self.exportInstanceObjName(instancedMats, i, instancedShapes))
800 self.exportMaterialLink(file, mat)
801 for shape in shapeList:
802 blenderExportVertexMap = []
805 ffaces = [f for f in mesh.faces if (f.mat == matIndex) and (f.smooth in smoothFltr[shape])]
810 # v = [vertex.co[0], vertex.co[1], vertex.co[2]]
812 if normalFltr[shape]:
814 # v.extend(vertex.no)
819 if (uvFltr[shape]) and (mesh.faceUV):
820 # v.extend(face.uv[index])
821 v.append(face.uv[index])
822 blenderVIndex = vertex.index
825 if (blenderVIndex < len(blenderExportVertexMap)):
826 for exportVIndex in blenderExportVertexMap[blenderVIndex]:
827 v2 = exportVerts[exportVIndex]
828 if (length==len(v2)) and (v == v2):
829 newExportVIndex = exportVIndex
831 if (newExportVIndex < 0):
832 newExportVIndex = len(exportVerts)
833 exportVerts.append(v)
834 while blenderVIndex >= len(blenderExportVertexMap):
835 blenderExportVertexMap.append([])
836 blenderExportVertexMap[blenderVIndex].append(newExportVIndex)
837 exportVIndices.append(newExportVIndex)
839 exportFaces.append(exportVIndices)
840 if (len(exportVerts)>0):
841 mesh_str = self.getMeshType(len(exportVerts), mats[matIndex], instancedMats)
843 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
845 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
846 for face in exportFaces:
847 file.write("%d %d %d\n"%(face[0], face[1], face[2]))
849 file.write("%d %d %d\n"%(face[0], face[2], face[3]))
850 file.write("\t] \"point P\" [\n")
851 # for vertex in exportVerts:
852 # file.write("%f %f %f\n"%(vertex[0], vertex[1], vertex[2]))
853 file.write("".join(["%f %f %f\n"%tuple(vertex[0]) for vertex in exportVerts]))
854 if normalFltr[shape]:
855 file.write("\t] \"normal N\" [\n")
856 # for vertex in exportVerts:
857 # file.write("%f %f %f\n"%(vertex[3], vertex[4], vertex[5]))
858 file.write("".join(["%f %f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
859 if (uvFltr[shape]) and (mesh.faceUV):
860 file.write("\t] \"float uv\" [\n")
861 # for vertex in exportVerts:
862 # file.write("%f %f\n"%(vertex[6], vertex[7]))
863 file.write("".join(["%f %f\n"%tuple(vertex[2]) for vertex in exportVerts]))
865 if (uvFltr[shape]) and (mesh.faceUV):
866 file.write("\t] \"float uv\" [\n")
867 # for vertex in exportVerts:
868 # file.write("%f %f\n"%(vertex[3], vertex[4]))
869 file.write("".join(["%f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
872 file.write("ObjectEnd # %s\n\n" % self.exportInstanceObjName(instancedMats, i, instancedShapes))
873 #print(" shape(%s): %d vertices, %d faces"%(shapeText[shape], len(exportVerts), len(exportFaces)))
875 # If we changed the active UV layer: reset it to the original.
876 if renderUVLayer != activeUVLayer_orig:
877 mesh.activeUVLayer = activeUVLayer_orig
880 #-------------------------------------------------
881 # exportMeshes(self, file)
882 # exports meshes that uses instancing (meshes that are used by at least "instancing_threshold" objects)
883 #-------------------------------------------------
884 def exportMeshes(self, file):
885 scn = Scene.GetCurrent()
886 instancing_threshold = luxProp(scn, "instancing_threshold", 2).get()
887 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true")
889 #pb = exportProgressBar(len(self.meshes), self.mpb)
890 for (mesh_name, objs) in self.meshes.items():
891 #pb.counter('Exporting Meshes')
892 self.instances[mesh_name] = {'obj_mats':{}, 'obj_vols':{}, 'obj_mods':{}}
893 allow_instancing = True
894 mats = getMaterials(objs[0])
895 for mat in mats: # don't instance if one of the materials is emissive
896 if (mat!=None) and (luxProp(mat, "type", "").get()=="light"):
897 allow_instancing = False
899 obj_mats = getMaterials(obj)
900 obj_name = obj.getName()
902 obj_mats_used = getMaterials(obj, True)
903 # if an instance overrides mesh's materials, copy them
904 self.instances[mesh_name]['obj_mats'][obj_name] = obj_mats_used
905 # lets not forget volume definitions in overridden materials
906 self.instances[mesh_name]['obj_vols'][obj_name] = {}
907 for obj_mat in obj_mats_used:
908 self.instances[mesh_name]['obj_vols'][obj_name][obj_mat.name] = {}
909 for volume_prop in ['Exterior', 'Interior']:
910 if luxProp(obj_mat, '%s_vol_used'%(volume_prop), 'false').get() == 'true':
911 volId = luxProp(obj_mat, '%s_vol_id' % (volume_prop), 0).get()
914 self.instances[mesh_name]['obj_vols'][obj_name][obj_mat.name][volume_prop] = volId
915 if not 'mesh_mats' in self.instances[mesh_name]:
916 self.instances[mesh_name]['mesh_mats'] = getMaterials(objs[0])
917 self.instances[mesh_name]['mesh_mats_used'] = getMaterials(objs[0], True)
918 obj_mods = getModifiers(obj)
919 # collect modifier configurations to export all possible shapes later
921 self.instances[mesh_name]['obj_mods'][obj_mods].append(obj_name)
923 self.instances[mesh_name]['obj_mods'][obj_mods] = [obj_name]
924 if allow_instancing and (len(objs) >= instancing_threshold):
925 del self.meshes[mesh_name]
926 j = 0 if len(self.instances[mesh_name]['obj_mods']) > 1 else None
927 for shape in self.instances[mesh_name]['obj_mods'].values():
928 mesh.getFromObject(shape[0], 0, 1)
929 #print("blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
930 if not self.instances[mesh_name].has_key('mesh_mats_used'):
931 file.write("ObjectBegin \"%s\"\n" % self.exportInstanceObjName(mesh_name, shapeId=j))
932 if (mesh_optimizing.get() == "true"):
933 self.exportMeshOpt(file, mesh, mats, mesh_name, instancedShapes=j)
935 self.exportMesh(file, mesh, mats, mesh_name, instancedShapes=j)
936 file.write("ObjectEnd # %s\n\n" % self.exportInstanceObjName(mesh_name, shapeId=j))
938 if (mesh_optimizing.get() == "true"):
939 self.exportMeshOpt(file, mesh, mats, mesh_name, instancedMats=mesh_name, instancedShapes=j)
941 self.exportMesh(file, mesh, mats, mesh_name, instancedMats=mesh_name, instancedShapes=j)
942 if j is not None: j += 1
945 #-------------------------------------------------
946 # exportObjects(self, file)
947 # exports objects to the file
948 #-------------------------------------------------
949 def exportObjects(self, file):
950 # write transformation matrix without losing float precision
951 def preciseMatrix(m):
953 for i in range(len(m)):
955 if type(v) is not float: l.append(preciseMatrix(v))
956 elif abs(v) in [0, 1.0]: l.append('%0.1f' % v)
957 else: l.append('%0.18f' % v)
959 scn = Scene.GetCurrent()
960 #cam = scn.getCurrentCamera().data
961 cam = scn.objects.camera.data
962 objectmblur = luxProp(cam, "objectmblur", "true").get()
963 usemblur = luxProp(cam, "usemblur", "false").get()
964 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true").get()
966 #pb = exportProgressBar(len(self.objects), self.mpb)
967 for [obj, matrix] in self.objects:
968 #pb.counter('Exporting Objects')
969 #print("object: %s"%(obj.getName()))
970 mesh_name = obj.getData(name_only=True)
971 obj_name = obj.getName()
974 if objectmblur == "true" and usemblur == "true":
977 motion = self.hair['motion'][obj]
979 frame = Blender.Get('curframe')
980 Blender.Set('curframe', frame+1)
982 Blender.Set('curframe', frame)
984 #print(" motion blur")
987 if motion: # motion-blur only works with instances, so ensure mesh is exported as instance first
988 if mesh_name in self.meshes:
989 del self.meshes[mesh_name]
990 j = 0 if len(self.instances[mesh_name]['obj_mods']) > 1 else None
991 for shape in self.instances[mesh_name]['obj_mods'].values():
992 mesh.getFromObject(Object.Get(shape[0]), 0, 1)
993 mats = getMaterials(obj)
994 #print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
995 if not self.instances[mesh_name].has_key('mesh_mats_used'):
996 file.write("ObjectBegin \"%s\"\n" % self.exportInstanceObjName(mesh_name, shapeId=j))
997 if mesh_optimizing == "true":
998 self.exportMeshOpt(file, mesh, mats, mesh_name, instancedShapes=j)
1000 self.exportMesh(file, mesh, mats, mesh_name, instancedShapes=j)
1001 file.write("ObjectEnd # %s\n\n" % self.exportInstanceObjName(mesh_name, shapeId=j))
1003 if mesh_optimizing == "true":
1004 self.exportMeshOpt(file, mesh, mats, mesh_name, instancedMats=mesh_name, instancedShapes=j)
1006 self.exportMesh(file, mesh, mats, mesh_name, instancedMats=mesh_name, instancedShapes=j)
1007 if j is not None: j += 1
1009 j = 0 if len(self.instances[mesh_name]['obj_mods']) > 1 else None
1010 for shape in self.instances[mesh_name]['obj_mods'].values():
1011 if shape != ['luxHair'] and not obj_name in shape:
1014 i = 0 if self.instances[mesh_name].has_key('mesh_mats_used') else None
1015 for mat in self.instances[mesh_name]['mesh_mats_used'] if self.instances[mesh_name].has_key('mesh_mats_used') else [None]:
1016 file.write("AttributeBegin # %s\n" % self.exportInstanceObjName(obj_name, i, j))
1017 file.write("\tTransform [%s]\n" % preciseMatrix(matrix))
1019 file.write("\tTransformBegin\n")
1020 file.write("\t\tIdentity\n")
1021 file.write("\t\tTransform [%s]\n" % preciseMatrix(motion))
1022 file.write("\t\tCoordinateSystem \"%s\"\n" % (self.exportInstanceObjName(obj_name, i, j)+'_motion'))
1023 file.write("\tTransformEnd\n")
1024 if mesh_name in self.meshes:
1025 mesh.getFromObject(obj, 0, 1)
1026 mats = getMaterials(obj)
1027 #print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
1028 if mesh_optimizing == "true":
1029 self.exportMeshOpt(file, mesh, mats, mesh_name)
1031 self.exportMesh(file, mesh, mats, mesh_name)
1033 #print(" instance %s"%(mesh_name))
1034 if mat is not None and obj_name in self.instances[mesh_name]['obj_mats']: #and self.instances[mesh_name]['mesh_mats'] != getMaterials(obj):
1035 file.write("\tNamedMaterial \"%s\"\n" % self.instances[mesh_name]['obj_mats'][obj_name][i].name)
1036 for volume_prop in ['Exterior', 'Interior']:
1037 vol = self.instances[mesh_name]['obj_vols'][obj_name][self.instances[mesh_name]['obj_mats'][obj_name][i].name][volume_prop]
1038 file.write("\t%s \"%s\"\n" % (volume_prop, '' if type(vol) is str else getNamedVolume(vol)['name']))
1040 file.write("\tMotionInstance \"%s\" 0.0 1.0 \"%s\"\n" % (self.exportInstanceObjName(mesh_name, i, j), self.exportInstanceObjName(obj_name, i, j)+'_motion'))
1042 file.write("\tObjectInstance \"%s\"\n" % self.exportInstanceObjName(mesh_name, i, j))
1043 file.write("AttributeEnd\n\n")
1044 if i is not None: i += 1
1045 if j is not None: j += 1
1048 #-------------------------------------------------
1049 # exportPortals(self, file)
1050 # exports portals objects to the file
1051 #-------------------------------------------------
1052 def exportPortals(self, file):
1053 scn = Scene.GetCurrent()
1054 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true")
1056 for [obj, matrix] in self.portals:
1057 #print("portal: %s"%(obj.getName()))
1058 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
1059 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
1060 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
1061 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
1062 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
1063 mesh_name = obj.getData(name_only=True)
1064 mesh.getFromObject(obj, 0, 1)
1065 mats = getMaterials(obj) # mats = obj.getData().getMaterials()
1066 if (mesh_optimizing.get() == "true"):
1067 self.exportMeshOpt(file, mesh, mats, mesh_name, True)
1069 self.exportMesh(file, mesh, mats, mesh_name, True)
1072 #-------------------------------------------------
1073 # exportLights(self, file)
1074 # exports lights to the file
1075 #-------------------------------------------------
1076 def exportLights(self, file):
1077 for [obj, matrix] in self.lights:
1078 ltype = obj.getData(mesh=1).getType() # data
1079 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
1080 lightgroup = luxProp(obj, "light.lightgroup", "default")
1081 if luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false").get() == "true":
1083 #print("light: %s"%(obj.getName()))
1084 if ltype == Lamp.Types["Area"]:
1085 (str, link) = luxLight("", "", obj, None, 0)
1087 if ltype == Lamp.Types["Area"]: file.write("AttributeBegin # %s\n"%obj.getName())
1088 else: file.write("TransformBegin # %s\n"%obj.getName())
1089 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
1090 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
1091 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
1092 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
1093 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
1094 col = obj.getData(mesh=1).col # data
1095 energy = obj.getData(mesh=1).energy # data
1096 if ltype == Lamp.Types["Lamp"]:
1097 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
1098 file.write("LightGroup \"%s\"\n"%lightgroup.get())
1099 (str, link) = luxLamp("", "", obj, None, 0)
1100 file.write(str+"LightSource \"point\""+link+"\n")
1101 if ltype == Lamp.Types["Spot"]:
1102 (str, link) = luxSpot("", "", obj, None, 0)
1104 proj = luxProp(obj, "light.usetexproj", "false")
1105 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
1106 file.write("LightGroup \"%s\"\n"%lightgroup.get())
1107 if(proj.get() == "true"):
1108 file.write("Rotate 180 0 1 0\n")
1109 file.write("LightSource \"projection\" \"float fov\" [%f]"%(obj.getData(mesh=1).spotSize))
1111 file.write("LightSource \"spot\" \"point from\" [0 0 0] \"point to\" [0 0 -1] \"float coneangle\" [%f] \"float conedeltaangle\" [%f]"\
1112 %(obj.getData(mesh=1).spotSize*0.5, obj.getData(mesh=1).spotSize*0.5*obj.getData(mesh=1).spotBlend)) # data
1113 file.write(link+"\n")
1114 if ltype == Lamp.Types["Area"]:
1115 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
1116 file.write("LightGroup \"%s\"\n"%lightgroup.get())
1117 file.write("\tAreaLightSource \"area\"")
1119 # file.write(luxLight("", "", obj, None, 0))
1121 areax = obj.getData(mesh=1).getAreaSizeX()
1122 # lamps "getAreaShape()" not implemented yet - so we can't detect shape! Using square as default
1124 if (True): areay = areax
1125 else: areay = obj.getData(mesh=1).getAreaSizeY()
1126 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})
1127 if ltype == Lamp.Types["Area"]: file.write("AttributeEnd # %s\n"%obj.getName())
1128 else: file.write("TransformEnd # %s\n"%obj.getName())
1132 #-------------------------------------------------
1133 # exportVolumes(self, file)
1134 # exports volumes to the file
1135 #-------------------------------------------------
1136 def exportVolumes(self, file):
1137 #pb = exportProgressBar(len(self.volumes), self.mpb)
1138 for [obj, matrix] in self.volumes:
1139 #pb.counter('Exporting Volumes')
1140 #print("volume: %s"%(obj.getName()))
1141 file.write("# Volume: %s\n"%(obj.getName()))
1143 # trickery to obtain objectspace boundingbox AABB
1144 mat = obj.matrixWorld.copy().invert()
1145 bb = [vec * mat for vec in obj.getBoundBox()]
1146 minx = miny = minz = 100000000000000.0
1147 maxx = maxy = maxz = -100000000000000.0
1149 if (vec[0] < minx): minx = vec[0]
1150 if (vec[1] < miny): miny = vec[1]
1151 if (vec[2] < minz): minz = vec[2]
1152 if (vec[0] > maxx): maxx = vec[0]
1153 if (vec[1] > maxy): maxy = vec[1]
1154 if (vec[2] > maxz): maxz = vec[2]
1156 file.write("Transform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
1157 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
1158 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
1159 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
1160 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
1162 str_opt = (" \"point p0\" [%f %f %f] \"point p1\" [%f %f %f]"%(minx, miny, minz, maxx, maxy, maxz))
1163 mats = getMaterials(obj)
1164 if (len(mats)>0) and (mats[0]!=None) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
1166 (str, link) = luxMaterialBlock("", "", "", mat, None, 0, str_opt)
1167 file.write("%s"%link)
1171 # Note - radiance - this is a work in progress
1172 def luxFlashBlock(camObj):
1174 str += "CoordSysTransform \"camera\"\n"
1176 str += "Texture \"camflashtex\" \"color\" \"blackbody\" \"float temperature\" [5500.0]"
1177 str += "AreaLightSource \"area\" \"texture L\" [\"camflashtex\"] \"float power\" [100.000000] \"float efficacy\" [17.000000] \"float gain\" [1.000000]\n"
1181 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"
1185 class exportProgressBar(object):
1192 def __init__(self, ts, other=None):
1194 self.counterStep = 0
1196 # Master progress indicator
1197 self.totalSteps = self.realSteps
1198 self.currentStep = 0
1200 # sub-progress of another progress indicator
1201 self.totalSteps = self.realSteps * other.totalSteps
1202 self.currentStep = self.realSteps * (other.currentStep-1)
1206 return '<progress total:%i real:%i current:%i count:%i frac:%f>' % (self.totalSteps, self.realSteps, self.currentStep, self.counterStep, self.get_frac())
1209 return float(self.currentStep) / float(self.totalSteps)
1211 def next(self, msg):
1212 amt = self.get_frac()
1213 Window.DrawProgressBar(amt, msg)
1214 #print('%s %s'%(self,msg))
1216 self.currentStep += 1
1218 def counter(self, prefix):
1220 amt = self.get_frac()
1222 msg = '%s (%i/%i)' % (prefix, self.counterStep, self.realSteps)
1224 msg = '%s (%i/%i)' % (prefix, self.counterStep, self.totalSteps)
1225 Window.DrawProgressBar(amt, msg)
1226 #print('%s %s'%(self,msg))
1228 self.currentStep += 1
1229 self.counterStep += 1
1232 if not self.subMode:
1233 Window.DrawProgressBar(1.0, 'Finished')
1236 ######################################################
1238 ######################################################
1242 def save_lux(filename, unindexedname, anim_progress=None):
1243 global meshlist, matnames, lxs_filename, geom_filename, geom_pfilename, mat_filename, mat_pfilename, vol_filename, vol_pfilename, LuxIsGUI
1246 pb = exportProgressBar(12, anim_progress)
1250 global render_status_text
1251 global render_status
1252 render_status_text = 'Exporting...'
1253 render_status = True
1255 print("LuxRender Export started...\n")
1256 time1 = Blender.sys.time()
1257 scn = Scene.GetCurrent()
1259 filepath = os.path.dirname(filename)
1260 filebase = os.path.splitext(os.path.basename(filename))[0]
1262 lxs_filename = filename
1264 geom_filename = os.path.join(filepath, filebase + "-geom.lxo")
1265 geom_pfilename = filebase + "-geom.lxo"
1267 mat_filename = os.path.join(filepath, filebase + "-mat.lxm")
1268 mat_pfilename = filebase + "-mat.lxm"
1270 vol_filename = os.path.join(filepath, filebase + "-vol.lxv")
1271 vol_pfilename = filebase + "-vol.lxv"
1273 ### Zuegs: initialization for export class
1274 export = luxExport(Blender.Scene.GetCurrent(), pb)
1276 # check if a light is present
1277 envtype = luxProp(scn, "env.type", "infinite").get()
1278 skycomponent = luxProp(scn, "env.sunsky.skycomponent", "true").get()
1279 suncomponent = luxProp(scn, "env.sunsky.suncomponent", "true").get()
1280 if envtype == "sunsky":
1282 for obj in scn.objects:
1283 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
1284 if obj.getData(mesh=1).getType() == 1: # sun object # data
1286 if not(export.analyseScene()) and not(envtype == "infinite") and not(envtype == "infinitesample") \
1287 and not (envtype == "sunsky" and sun != None and suncomponent == "true") \
1288 and not (envtype == "sunsky" and skycomponent == "true"):
1289 print("ERROR: No light source found")
1290 Draw.PupMenu("ERROR: No light source found%t|OK%x1")
1291 render_status_text = ''
1292 render_status = False
1293 Blender.Window.QRedrawAll()
1297 # check render region dimensions > 0
1298 if scn.getRenderingContext().borderRender:
1299 border = scn.getRenderingContext().border
1300 if (border[0]==border[2]) or (border[1]==border[3]):
1301 Draw.PupMenu("ERROR: Empty render region, use SHIFT-B to set render region in Blender%t|OK%x1")
1302 render_status_text = ''
1303 render_status = False
1304 Blender.Window.QRedrawAll()
1308 if LuxIsGUI: pb.next('Setting up Scene file')
1310 class output_proxy():
1312 combine_all_output = False
1315 if self.f is not None: self.f.close()
1316 def write(self, str):
1317 if self.f is not None:
1321 class file_output(output_proxy):
1322 def __init__(self,filename):
1323 self.f = open(filename, "w")
1325 from threading import Thread
1326 class pipe_output(output_proxy, Thread):
1327 combine_all_output = True
1329 def __init__(self, xr,yr, haltspp, halttime, filename):
1330 Thread.__init__(self)
1332 self.filename = filename
1333 self.haltspp = haltspp
1334 self.halttime = halttime
1338 if self.haltspp > 0 or self.halttime > 0:
1339 bintype = "luxconsole"
1340 self.load_result = True
1342 bintype = "luxrender"
1344 print("pipe: using %s" % bintype)
1346 self.p = get_lux_pipe(scn, 1, bintype)
1347 self.f = self.p.stdin
1349 global render_status_text
1350 global render_status
1351 render_status = True
1352 render_status_text = "Rendering ..."
1353 Blender.Window.QRedrawAll()
1357 if self.load_result: self.data = self.p.communicate()[0]
1359 if self.load_result: # self.load_image()
1361 print("LuxRender process finished")
1362 self.update_status()
1364 def load_image(self):
1365 i = Blender.Image.Load(self.filename)
1369 def load_data(self):
1370 print("processing %i image bytes" % len(self.data))
1371 i = Blender.Image.New('luxrender', self.xr, self.yr, 32)
1374 raw_image.append(ord(j))
1377 for y in range(self.yr-1, -1, -1):
1378 for x in range(0, self.xr):
1379 i.setPixelI(x,y, raw_image[bi:bi+3]+[0])
1383 def update_status(self):
1384 global render_status_text
1385 global render_status
1386 render_status = False
1387 render_status_text = "Rendering complete"
1388 if self.haltspp > 0 or self.halttime > 0: render_status_text += ", check Image Editor window"
1389 Blender.Window.QRedrawAll()
1391 use_pipe_output = luxProp(scn, "pipe", "false").get() == "true" and luxProp(scn, "run", "true").get() == "true"
1393 file = output_proxy()
1395 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
1396 ##### Determine/open files
1398 print("using pipe output")
1399 print("Exporting scene to pipe")
1400 xr,yr = get_render_resolution(scn)
1401 file = pipe_output(xr, yr,
1402 luxProp(scn, "haltspp", 0).get(),
1403 luxProp(scn, "halttime", 0).get(),
1404 os.path.join(filepath, filebase + ".png")
1407 print("using file output")
1408 print("Exporting scene to '" + filename + "'...\n")
1409 file = file_output(filename)
1411 ##### Write Header ######
1412 file.write("# LuxRender v%s Scene File\n"%__version__)
1413 file.write("# Exported by LuxBlend Blender Exporter\n")
1416 ##### Write camera ######
1417 #camObj = scn.getCurrentCamera()
1418 camObj = scn.objects.camera
1420 if LuxIsGUI: pb.next('Exporting Camera')
1422 print("processing Camera...")
1424 cammblur = luxProp(cam, "cammblur", "true")
1425 usemblur = luxProp(cam, "usemblur", "false")
1427 matrix = camObj.getMatrix()
1430 if(cammblur.get() == "true" and usemblur.get() == "true"):
1432 frame = Blender.Get('curframe')
1433 Blender.Set('curframe', frame+1)
1434 m1 = 1.0*matrix # multiply by 1.0 to get a copy of original matrix (will be frame-independant)
1435 Blender.Set('curframe', frame)
1437 # Motion detected, write endtransform
1438 print(" motion blur")
1442 target = pos + forwards
1444 file.write("TransformBegin\n")
1445 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] ))
1446 file.write(" CoordinateSystem \"CameraEndTransform\"\n")
1447 file.write("TransformEnd\n\n")
1449 # Write original lookat transform
1451 forwards = -matrix[2]
1452 target = pos + forwards
1454 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] ))
1455 file.write(luxCamera(camObj.data, scn.getRenderingContext()))
1457 file.write("\n \"string endtransform\" [\"CameraEndTransform\"]")
1461 if LuxIsGUI: pb.next('Exporting Film Settings')
1462 ##### Write film ######
1463 file.write(luxFilm(scn))
1466 if LuxIsGUI: pb.next('Exporting Pixel Filter')
1467 ##### Write Pixel Filter ######
1468 file.write(luxPixelFilter(scn))
1471 if LuxIsGUI: pb.next('Exporting Sampler')
1472 ##### Write Sampler ######
1473 file.write(luxSampler(scn))
1476 if LuxIsGUI: pb.next('Exporting Surface Integrator')
1477 ##### Write Surface Integrator ######
1478 file.write(luxSurfaceIntegrator(scn))
1481 if LuxIsGUI: pb.next('Exporting Volume Integrator')
1482 ##### Write Volume Integrator ######
1483 file.write(luxVolumeIntegrator(scn))
1486 if LuxIsGUI: pb.next('Exporting Accelerator')
1487 ##### Write Acceleration ######
1488 file.write(luxAccelerator(scn))
1491 ########## BEGIN World
1493 file.write("WorldBegin\n")
1496 ########## World scale
1497 #scale = luxProp(scn, "global.scale", 1.0).get()
1499 # # TODO: not working yet !!!
1500 # # TODO: propabily scale needs to be applyed on camera coords too
1501 # 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))
1504 if LuxIsGUI: pb.next('Exporting Environment')
1505 ##### Write World Background, Sunsky or Env map ######
1506 env = luxEnvironment(scn)
1508 # switch env type from infinite to infinitesample if there are no portals in the scene
1509 if luxProp(scn, "env.type", "infinite").get() == "infinite" and not export.portals:
1510 luxProp(scn, "env.type", "infinite").set("infinitesample")
1511 env = luxEnvironment(scn)
1513 file.write("AttributeBegin\n")
1515 export.exportPortals(file)
1516 file.write("AttributeEnd\n")
1519 # Note - radiance - this is a work in progress
1520 # flash = luxFlashBlock(camObj)
1522 # file.write("# Camera flash lamp\n")
1523 # file.write("AttributeBegin\n")
1524 # #file.write("CoordSysTransform \"camera\"\n")
1526 # file.write("AttributeEnd\n\n")
1528 #### Write material & geometry file includes in scene file
1529 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(mat_pfilename))
1530 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(geom_pfilename))
1531 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(vol_pfilename))
1533 if luxProp(scn, "lxm", "true").get()=="true" or use_pipe_output:
1534 if LuxIsGUI: pb.next('Exporting Materials')
1535 ##### Write Material file #####
1536 if not file.combine_all_output: print("Exporting materials to '" + mat_filename + "'...\n")
1537 mat_file = open(mat_filename, 'w') if not file.combine_all_output else file
1539 export.exportMaterials(mat_file)
1541 export.exportNamedVolumes(mat_file)
1543 if not file.combine_all_output: mat_file.close()
1545 if luxProp(scn, "lxo", "true").get()=="true" or use_pipe_output:
1546 if LuxIsGUI: pb.next('Exporting Geometry')
1547 ##### Write Geometry file #####
1548 if not file.combine_all_output: print("Exporting geometry to '" + geom_filename + "'...\n")
1549 geom_file = open(geom_filename, 'w') if not file.combine_all_output else file
1552 export.exportLights(geom_file)
1553 export.exportMeshes(geom_file)
1554 export.exportHairSystems(geom_file)
1555 export.exportObjects(geom_file)
1557 if not file.combine_all_output: geom_file.close()
1559 if luxProp(scn, "lxv", "true").get()=="true" or use_pipe_output:
1560 if LuxIsGUI: pb.next('Exporting Volumes')
1561 ##### Write Volume file #####
1562 if not file.combine_all_output: print("Exporting volumes to '" + vol_filename + "'...\n")
1563 vol_file = open(vol_filename, 'w') if not file.combine_all_output else file
1566 export.exportVolumes(vol_file)
1568 if not file.combine_all_output: vol_file.close()
1570 render_status_text = ''
1571 render_status = False
1572 Blender.Window.QRedrawAll()
1574 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
1576 file.write("WorldEnd\n\n")
1579 if LuxIsGUI: pb.finished()
1580 print("Finished.\n")
1583 time2 = Blender.sys.time()
1584 print("Processing time: %f\n" %(time2-time1))
1587 #if luxProp(scn, "haltspp", 0).get() > 0:
1588 # Wait for piped luxconsole render thread to end
1591 # Don't launch it again as a piped scene is started implicitly
1596 ########################################################################
1597 #### Construct server string argument
1598 ########################################################################
1600 def networkstring(scn):
1602 if (luxProp(scn,"network","false").get() == "true"):
1603 if (luxProp(scn,"network_use_file","false").get() == "true"):
1604 where_to_look = luxProp(scn,"network_file_path","false").get()
1605 print "Reading rendering slaves list from the file:", where_to_look
1607 f = open(where_to_look)
1610 if s and s[0] != '#':
1611 print " adding slave:", s
1612 servers_string += " -u " + s
1615 print "There was an error encountered while reading a file", where_to_look
1616 elif luxProp(scn,"network_servers","").get():
1617 for server in luxProp(scn,"network_servers","").get().split(","):
1618 servers_string=servers_string+" -u "+ server
1619 return servers_string
1622 #########################################################################
1623 ### LAUNCH LuxRender AND RENDER CURRENT SCENE
1624 #########################################################################
1626 def get_lux_exec(scn, type="luxrender"):
1628 #get blenders 'bpydata' directory
1629 datadir=Blender.Get("datadir")
1631 ic = luxProp(scn, "lux", "").get()
1632 ic = Blender.sys.dirname(ic) + os.sep + type
1634 if osys.platform == "win32": ic = ic + ".exe"
1636 if type=="luxrender" and osys.platform == "darwin": ic = ic + ".app/Contents/MacOS/luxrender"
1640 def get_lux_args(filename, extra_args=[], anim=False):
1641 ostype = osys.platform
1642 scn = Scene.GetCurrent()
1644 ic = get_lux_exec(scn, type=(anim and 'luxconsole' or 'luxrender'))
1646 servers_string = networkstring(scn)
1647 update_int=luxProp(scn,"network_interval",180).get()
1649 checkluxpath = luxProp(scn, "checkluxpath", True).get()
1651 if sys.exists(ic) != 1:
1652 Draw.PupMenu("Error: LuxRender not found. Please set path on System page.%t|OK")
1654 autothreads = luxProp(scn, "autothreads", "true").get()
1655 threads = luxProp(scn, "threads", 1).get()
1656 luxnice = luxProp(scn, "luxnice", 0).get()
1657 noopengl = luxProp(scn, "noopengl", "false").get()
1659 if noopengl == "true" and not anim:
1660 extra_args.append("--noopengl")
1662 lux_args = "\"%s\" " % ic
1664 extra_args.append('%s'%servers_string)
1665 extra_args.append("-i %d " % update_int)
1667 if autothreads != "true":
1668 extra_args.append("--threads=%d " % threads)
1670 lux_args2 = ' '.join(extra_args)
1673 lux_args2 = " - " + lux_args2
1675 filename = "\"%s\"" % filename
1676 lux_args2 = lux_args2 + filename
1678 lux_args += lux_args2
1680 if ostype == "win32":
1682 if luxnice > 15: prio = "/low"
1683 elif luxnice > 5: prio = "/belownormal"
1684 elif luxnice > -5: prio = "/normal"
1685 elif luxnice > -15: prio = "/abovenormal"
1686 else: prio = "/high"
1689 cmd = "start /b %s \"\" %s" % (prio, lux_args)
1691 # if animation/luxconsole, start minimised and wait for completion
1692 cmd = "start /WAIT /MIN %s \"\" %s" % (prio, lux_args)
1694 # if ostype == "linux2" or ostype == "darwin":
1697 cmd = "(nice -n %d %s)&"%(luxnice, lux_args)
1699 cmd = "(nice -n %d %s)"%(luxnice, lux_args)
1701 return cmd, lux_args2
1703 def get_lux_pipe(scn, buf = 1024, type="luxconsole"):
1704 bin = "\"%s\"" % get_lux_exec(scn, type)
1706 print("piping to LuxRender binary: " + bin)
1708 PIPE = subprocess.PIPE
1710 cmd, raw_args = get_lux_args('-',
1711 extra_args=['-b'] if type=="luxconsole" else []
1714 # dirty hack to filter "noopengl" option from luxconsole args
1715 raw_args = raw_args.replace('--noopengl', '')
1717 return subprocess.Popen(bin + raw_args, shell=True, bufsize=buf, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1719 def launchLux(filename):
1720 cmd, raw_args = get_lux_args(filename, extra_args=[])
1721 print("Running LuxRender:\n"+cmd)
1724 def launchLuxWait(filename, anim=False):
1725 ostype = osys.platform
1726 cmd, raw_args = get_lux_args(filename, extra_args=[], anim=anim)
1728 if ostype == "win32":
1731 # if ostype == "linux2" or ostype == "darwin":
1733 subprocess.call(cmd,shell=True)
1735 #### SAVE ANIMATION ####
1738 #def save_anim(filename):
1740 # scn = Scene.GetCurrent()
1741 # to = luxProp(scn, 'export.threaded', 'true').get()
1742 # run = luxProp(scn, "run", "true").get()
1743 # deflt = luxProp(scn, "default", "true").get()
1744 # if to == 'true' and run == 'true' and deflt == 'false':
1746 # anim_thread = threading.Thread(target=save_anim_real, args=(filename,True))
1747 # anim_thread.start()
1749 # save_anim_real(filename)
1751 def save_anim(filename, as_thread=False):
1752 if as_thread: print('SAR thread started')
1753 global MatSaved, LuxIsGUI
1756 startF = Blender.Get('staframe')
1757 endF = Blender.Get('endframe')
1758 scn = Scene.GetCurrent()
1760 Run = luxProp(scn, "run", "true").get()
1763 haltspp = luxProp(scn, "haltspp", 0).get()
1764 halttime = luxProp(scn, "halttime", 0).get()
1765 if haltspp == 0 and halttime == 0:
1766 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")
1771 print("\n\nRendering animation (frame %i to %i)\n\n"%(startF, endF))
1773 v_frame = Blender.Get('curframe')
1776 if LuxIsGUI: pb = exportProgressBar(endF-startF +1)
1778 for i in range (startF, endF+1):
1779 if LuxIsGUI: pb.next('Exporting frame %d\n'%i)
1780 # Seems to get stuck unless we redraw the UI
1782 # Window.QRedrawAll()
1783 Blender.Set('curframe', i)
1784 print("Rendering frame %i"%(i))
1786 frameindex = ("-%05d" % (i)) + ".lxs"
1787 indexedname = sys.makename(filename, frameindex)
1788 unindexedname = filename
1789 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, "-%05d" % (Blender.Get('curframe'))))
1792 if save_lux(filename, unindexedname, pb):
1793 launchLuxWait(filename, anim=True)
1795 save_lux(indexedname, unindexedname, pb)
1798 # Seems to get stuck unless we redraw the UI
1800 # Window.QRedrawAll()
1802 if LuxIsGUI: pb.finished()
1804 Blender.Set('curframe', v_frame)
1806 print("\n\nFinished Rendering animation\n")
1807 if as_thread: print('SAR thread finished')
1809 #### SAVE STILL (hackish...) ####
1812 #def save_still(filename):
1814 # scn = Scene.GetCurrent()
1815 # to = luxProp(scn, 'export.threaded', 'true').get()
1816 # if to == 'true' and luxProp(scn, "run", "true").get() == "true":
1818 # still_thread = threading.Thread(target=save_still_real, args=(filename,))
1819 # still_thread.start()
1821 # save_still_real(filename)
1823 def save_still(filename):
1824 global MatSaved, runRenderAfterExport
1825 scn = Scene.GetCurrent()
1826 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, ""))
1828 unindexedname = filename
1829 # Seems to get stuck unless we redraw the UI
1831 # Window.QRedrawAll()
1832 if save_lux(filename, unindexedname):
1833 if runRenderAfterExport and luxProp(scn, "pipe", "false").get() == "false": #(run == None and luxProp(scn, "run", "true").get() == "true") or run:
1836 # Seems to get stuck unless we redraw the UI
1838 # Window.QRedrawAll()
1841 ######################################################
1843 ######################################################
1845 def base64value(char):
1846 if 64 < ord(char) < 91: return ord(char)-65
1847 if 96 < ord(char) < 123: return ord(char)-97+26
1848 if 47 < ord(char) < 58: return ord(char)-48+52
1849 if char == '+': return 62
1852 def decodeIconStr(s):
1853 buf = BGL.Buffer(BGL.GL_BYTE, [16,16,4])
1858 buf[y][x][c] = int(base64value(s[offset])*4.048)
1862 def decodeLogoStr(s):
1863 buf = BGL.Buffer(BGL.GL_BYTE, [18,118,4])
1866 for x in range(118):
1868 buf[y][x][c] = int(base64value(s[offset])*4.048)
1872 def decodeArrowStr(s):
1873 buf = BGL.Buffer(BGL.GL_BYTE, [22,22,4])
1878 buf[y][x][c] = int(base64value(s[offset])*4.048)
1882 def decodeBarStr(s):
1883 buf = BGL.Buffer(BGL.GL_BYTE, [17,138,4])
1886 for x in range(138):
1888 buf[y][x][c] = int(base64value(s[offset])*4.048)
1892 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")
1894 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")
1896 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")
1899 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")
1900 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")
1901 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")
1902 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")
1903 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")
1904 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")
1905 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")
1906 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")
1907 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")
1908 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")
1909 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")
1910 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")
1911 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")
1913 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")
1915 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")
1917 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")
1919 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")
1921 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")
1923 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")
1925 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")
1927 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")
1929 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")
1932 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")
1934 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//")
1936 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")
1938 def drawIcon(icon, x, y):
1939 BGL.glEnable(BGL.GL_BLEND)
1940 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1941 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1942 BGL.glDrawPixels(16, 16, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1943 BGL.glDisable(BGL.GL_BLEND)
1945 def drawArrow(icon, x, y):
1946 BGL.glEnable(BGL.GL_BLEND)
1947 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1948 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1949 BGL.glDrawPixels(22, 22, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1950 BGL.glDisable(BGL.GL_BLEND)
1952 def drawLogo(icon, x, y):
1953 BGL.glEnable(BGL.GL_BLEND)
1954 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1955 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1956 BGL.glDrawPixels(118, 18, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1957 BGL.glDisable(BGL.GL_BLEND)
1959 def drawBar(icon, x, y):
1960 BGL.glEnable(BGL.GL_BLEND)
1961 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1962 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1963 BGL.glDrawPixels(138, 17, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1964 BGL.glDisable(BGL.GL_BLEND)
1968 #-------------------------------------------------
1970 # helper class to handle images and icons for the GUI
1971 #-------------------------------------------------
1974 def resize(self, width, height):
1976 self.height = height
1977 self.buf = BGL.Buffer(BGL.GL_BYTE, [width,height,4]) # GL buffer
1978 def __init__(self, width=0, height=0):
1979 self.resize(width, height)
1980 def draw(self, x, y):
1981 BGL.glEnable(BGL.GL_BLEND)
1982 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1983 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1984 BGL.glDrawPixels(self.width, self.height, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, self.buf)
1985 BGL.glDisable(BGL.GL_BLEND)
1986 def decodeStr(self, width, height, s):
1987 self.resize(width, height)
1989 for y in range(self.height):
1990 for x in range(self.width):
1992 self.buf[y][x][c] = int(base64value(s[offset])*4.048)
1995 def decodeLuxConsole(self, width, height, data):
1996 self.resize(width, height)
1998 for y in range(self.height-1,-1,-1):
1999 for x in range(self.width):
2001 self.buf[y][x][c] = ord(data[offset])
2003 self.buf[y][x][3] = 255
2006 previewCache = {} # dictionary that will hold all preview images
2009 ######################################################
2011 ######################################################
2017 evtDeletePreset = 97
2018 evtSaveMaterial = 96
2019 evtLoadMaterial = 95
2020 evtDeleteMaterial = 94
2021 evtConvertMaterial = 92
2022 evtSaveMaterial2 = 91
2023 evtLoadMaterial2 = 90
2027 defaultsExclude = ['preset','filename','page','link','UID']
2029 luxdefaults = Blender.Registry.GetKey('luxblend', True)
2030 if not(type(luxdefaults) is DictType):
2034 newluxdefaults = luxdefaults.copy()
2037 def saveluxdefaults():
2038 try: del newluxdefaults['page']
2040 try: Blender.Registry.SetKey('luxblend', newluxdefaults, True)
2047 # *** PRESETS **************************************
2048 presetsExclude = ['preset','lux','datadir','threads','filename','page','RGC','film.gamma','colorclamp','link']
2049 def getPresets(key):
2050 presets = Blender.Registry.GetKey(key, True)
2051 if not(type(presets) is DictType):
2054 def getScenePresets():
2055 presets = getPresets('luxblend_presets').copy()
2057 # radiance's hardcoded render presets:
2059 presets['0 Preview - Global Illumination'] = {
2060 'film.displayinterval': 4,
2063 'useparamkeys': 'false',
2064 'sampler.showadvanced': 'false',
2065 'sintegrator.showadvanced': 'false',
2066 'pixelfilter.showadvanced': 'false',
2068 'sampler.type': 'lowdiscrepancy',
2069 'sampler.lowdisc.pixelsamples': 1,
2070 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
2072 'sintegrator.type': 'distributedpath',
2073 'sintegrator.distributedpath.directsampleall': 'true',
2074 'sintegrator.distributedpath.directsamples': 1,
2075 'sintegrator.distributedpath.directdiffuse': 'true',
2076 'sintegrator.distributedpath.directglossy': 'true',
2077 'sintegrator.distributedpath.indirectsampleall': 'false',
2078 'sintegrator.distributedpath.indirectsamples': 1,
2079 'sintegrator.distributedpath.indirectdiffuse': 'true',
2080 'sintegrator.distributedpath.indirectglossy': 'true',
2081 'sintegrator.distributedpath.diffusereflectdepth': 1,
2082 'sintegrator.distributedpath.diffusereflectsamples': 4,
2083 'sintegrator.distributedpath.diffuserefractdepth': 4,
2084 'sintegrator.distributedpath.diffuserefractsamples': 1,
2085 'sintegrator.distributedpath.glossyreflectdepth': 1,
2086 'sintegrator.distributedpath.glossyreflectsamples': 2,
2087 'sintegrator.distributedpath.glossyrefractdepth': 4,
2088 'sintegrator.distributedpath.glossyrefractsamples': 1,
2089 'sintegrator.distributedpath.specularreflectdepth': 2,
2090 'sintegrator.distributedpath.specularrefractdepth': 4,
2091 'sintegrator.distributedpath.causticsonglossy': 'true',
2092 'sintegrator.distributedpath.causticsondiffuse': 'false',
2093 'sintegrator.distributedpath.strategy': 'auto',
2095 'pixelfilter.type': 'mitchell',
2096 'pixelfilter.mitchell.sharp': 0.250,
2097 'pixelfilter.mitchell.xwidth': 2.0,
2098 'pixelfilter.mitchell.ywidth': 2.0,
2099 'pixelfilter.mitchell.optmode': "slider" }
2101 presets['0b Preview - Direct Lighting'] = {
2102 'film.displayinterval': 4,
2105 'useparamkeys': 'false',
2106 'sampler.showadvanced': 'false',
2107 'sintegrator.showadvanced': 'false',
2108 'pixelfilter.showadvanced': 'false',
2110 'sampler.type': 'lowdiscrepancy',
2111 'sampler.lowdisc.pixelsamples': 1,
2112 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
2114 'sintegrator.type': 'directlighting',
2115 'sintegrator.dlighting.maxdepth': 5,
2117 'pixelfilter.type': 'mitchell',
2118 'pixelfilter.mitchell.sharp': 0.3333,
2119 'pixelfilter.mitchell.xwidth': 1.5,
2120 'pixelfilter.mitchell.ywidth': 1.5,
2121 'pixelfilter.mitchell.supersample': "true",
2122 'pixelfilter.mitchell.optmode': "slider" }
2124 presets['1 Final - MLT/Bidir Path Tracing (interior) (recommended)'] = {
2125 'film.displayinterval': 8,
2128 'useparamkeys': 'false',
2129 'sampler.showadvanced': 'false',
2130 'sintegrator.showadvanced': 'false',
2131 'pixelfilter.showadvanced': 'false',
2133 'sampler.type': 'metropolis',
2134 'sampler.metro.strength': 0.6,
2135 'sampler.metro.lmprob': 0.4,
2136 'sampler.metro.maxrejects': 512,
2137 #'sampler.metro.initsamples': 262144,
2138 'sampler.metro.usevariance': "false",
2140 'sintegrator.type': 'bidirectional',
2141 'sintegrator.bidir.bounces': 16,
2142 'sintegrator.bidir.eyedepth': 16,
2143 'sintegrator.bidir.lightdepth': 16,
2145 'pixelfilter.type': 'mitchell',
2146 'pixelfilter.mitchell.sharp': 0.3333,
2147 'pixelfilter.mitchell.xwidth': 1.5,
2148 'pixelfilter.mitchell.ywidth': 1.5,
2149 'pixelfilter.mitchell.supersample': "true",
2150 'pixelfilter.mitchell.optmode': "slider" }
2152 presets['2 Final - MLT/Path Tracing (exterior)'] = {
2153 'film.displayinterval': 8,
2156 'useparamkeys': 'false',
2157 'sampler.showadvanced': 'false',
2158 'sintegrator.showadvanced': 'false',
2159 'pixelfilter.showadvanced': 'false',
2161 'sampler.type': 'metropolis',
2162 'sampler.metro.strength': 0.6,
2163 'sampler.metro.lmprob': 0.4,
2164 'sampler.metro.maxrejects': 512,
2165 #'sampler.metro.initsamples': 262144,
2166 'sampler.metro.usevariance': "false",
2168 'sintegrator.type': 'path',
2169 'sintegrator.bidir.bounces': 10,
2170 'sintegrator.bidir.maxdepth': 10,
2172 'pixelfilter.type': 'mitchell',
2173 'pixelfilter.mitchell.sharp': 0.3333,
2174 'pixelfilter.mitchell.xwidth': 1.5,
2175 'pixelfilter.mitchell.ywidth': 1.5,
2176 'pixelfilter.mitchell.supersample': "true",
2177 'pixelfilter.mitchell.optmode': "slider" }
2181 presets['5 Progressive - Bidir Path Tracing (interior)'] = {
2182 'film.displayinterval': 8,
2185 'useparamkeys': 'false',
2186 'sampler.showadvanced': 'false',
2187 'sintegrator.showadvanced': 'false',
2188 'pixelfilter.showadvanced': 'false',
2190 'sampler.type': 'lowdiscrepancy',
2191 'sampler.lowdisc.pixelsamples': 1,
2192 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
2194 'sintegrator.type': 'bidirectional',
2195 'sintegrator.bidir.bounces': 16,
2196 'sintegrator.bidir.eyedepth': 16,
2197 'sintegrator.bidir.lightdepth': 16,
2199 'pixelfilter.type': 'mitchell',
2200 'pixelfilter.mitchell.sharp': 0.3333,
2201 'pixelfilter.mitchell.xwidth': 1.5,
2202 'pixelfilter.mitchell.ywidth': 1.5,
2203 'pixelfilter.mitchell.supersample': "true",
2204 'pixelfilter.mitchell.optmode': "slider" }
2206 presets['6 Progressive - Path Tracing (exterior)'] = {
2207 'film.displayinterval': 8,
2210 'useparamkeys': 'false',
2211 'sampler.showadvanced': 'false',
2212 'sintegrator.showadvanced': 'false',
2213 'pixelfilter.showadvanced': 'false',
2215 'sampler.type': 'lowdiscrepancy',
2216 'sampler.lowdisc.pixelsamples': 1,
2217 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
2219 'sintegrator.type': 'path',
2220 'sintegrator.bidir.bounces': 10,
2221 'sintegrator.bidir.maxdepth': 10,
2223 'pixelfilter.type': 'mitchell',
2224 'pixelfilter.mitchell.sharp': 0.3333,
2225 'pixelfilter.mitchell.xwidth': 1.5,
2226 'pixelfilter.mitchell.ywidth': 1.5,
2227 'pixelfilter.mitchell.supersample': "true",
2228 'pixelfilter.mitchell.optmode': "slider" }
2232 presets['8 Bucket - Bidir Path Tracing (interior)'] = {
2233 'film.displayinterval': 8,
2236 'useparamkeys': 'false',
2237 'sampler.showadvanced': 'false',
2238 'sintegrator.showadvanced': 'false',
2239 'pixelfilter.showadvanced': 'false',
2241 'sampler.type': 'lowdiscrepancy',
2242 'sampler.lowdisc.pixelsamples': 64,
2243 'sampler.lowdisc.pixelsampler': 'hilbert',
2245 'sintegrator.type': 'bidirectional',
2246 'sintegrator.bidir.bounces': 8,
2247 'sintegrator.bidir.eyedepth': 8,
2248 'sintegrator.bidir.lightdepth': 10,
2250 'pixelfilter.type': 'mitchell',
2251 'pixelfilter.mitchell.sharp': 0.3333,
2252 'pixelfilter.mitchell.xwidth': 1.5,
2253 'pixelfilter.mitchell.ywidth': 1.5,
2254 'pixelfilter.mitchell.supersample': "true",
2255 'pixelfilter.mitchell.optmode': "slider" }
2257 presets['9 Bucket - Path Tracing (exterior)'] = {
2258 'film.displayinterval': 8,
2261 'useparamkeys': 'false',
2262 'sampler.showadvanced': 'false',
2263 'sintegrator.showadvanced': 'false',
2264 'pixelfilter.showadvanced': 'false',
2266 'sampler.type': 'lowdiscrepancy',
2267 'sampler.lowdisc.pixelsamples': 64,
2268 'sampler.lowdisc.pixelsampler': 'hilbert',
2270 'sintegrator.type': 'path',
2271 'sintegrator.bidir.bounces': 8,
2272 'sintegrator.bidir.maxdepth': 8,
2274 'pixelfilter.type': 'mitchell',
2275 'pixelfilter.mitchell.sharp': 0.3333,
2276 'pixelfilter.mitchell.xwidth': 1.5,
2277 'pixelfilter.mitchell.ywidth': 1.5,
2278 'pixelfilter.mitchell.supersample': "true",
2279 'pixelfilter.mitchell.optmode': "slider" }
2283 presets['B Anim - Distributed/GI low Q'] = {
2284 'film.displayinterval': 8,
2287 'useparamkeys': 'false',
2288 'sampler.showadvanced': 'false',
2289 'sintegrator.showadvanced': 'false',
2290 'pixelfilter.showadvanced': 'false',
2292 'sampler.type': 'lowdiscrepancy',
2293 'sampler.lowdisc.pixelsamples': 16,
2294 'sampler.lowdisc.pixelsampler': 'hilbert',
2296 'sintegrator.type': 'distributedpath',
2297 'sintegrator.distributedpath.causticsonglossy': 'true',
2298 'sintegrator.distributedpath.diffuserefractdepth': 5,
2299 'sintegrator.distributedpath.indirectglossy': 'true',
2300 'sintegrator.distributedpath.directsamples': 1,
2301 'sintegrator.distributedpath.diffuserefractsamples': 1,
2302 'sintegrator.distributedpath.glossyreflectdepth': 2,
2303 'sintegrator.distributedpath.causticsondiffuse': 'false',
2304 'sintegrator.distributedpath.directsampleall': 'true',
2305 'sintegrator.distributedpath.indirectdiffuse': 'true',
2306 'sintegrator.distributedpath.specularreflectdepth': 3,
2307 'sintegrator.distributedpath.diffusereflectsamples': 1,
2308 'sintegrator.distributedpath.glossyreflectsamples': 1,
2309 'sintegrator.distributedpath.glossyrefractdepth': 5,
2310 'sintegrator.distributedpath.diffusereflectdepth': '2',
2311 'sintegrator.distributedpath.indirectsamples': 1,
2312 'sintegrator.distributedpath.indirectsampleall': 'false',
2313 'sintegrator.distributedpath.glossyrefractsamples': 1,
2314 'sintegrator.distributedpath.directdiffuse': 'true',
2315 'sintegrator.distributedpath.directglossy': 'true',
2316 'sintegrator.distributedpath.strategy': 'auto',
2317 'sintegrator.distributedpath.specularrefractdepth': 5,
2319 'pixelfilter.type': 'mitchell',
2320 'pixelfilter.mitchell.sharp': 0.3333,
2321 'pixelfilter.mitchell.xwidth': 1.5,
2322 'pixelfilter.mitchell.ywidth': 1.5,
2323 'pixelfilter.mitchell.supersample': "true",
2324 'pixelfilter.mitchell.optmode': "slider" }
2326 presets['C Anim - Distributed/GI medium Q'] = {
2327 'film.displayinterval': 8,
2330 'useparamkeys': 'false',
2331 'sampler.showadvanced': 'false',
2332 'sintegrator.showadvanced': 'false',
2333 'pixelfilter.showadvanced': 'false',
2335 'sampler.type': 'lowdiscrepancy',
2336 'sampler.lowdisc.pixelsamples': 64,
2337 'sampler.lowdisc.pixelsampler': 'hilbert',
2339 'sintegrator.type': 'distributedpath',
2340 'sintegrator.distributedpath.causticsonglossy': 'true',
2341 'sintegrator.distributedpath.diffuserefractdepth': 5,
2342 'sintegrator.distributedpath.indirectglossy': 'true',
2343 'sintegrator.distributedpath.directsamples': 1,
2344 'sintegrator.distributedpath.diffuserefractsamples': 1,
2345 'sintegrator.distributedpath.glossyreflectdepth': 2,
2346 'sintegrator.distributedpath.causticsondiffuse': 'false',
2347 'sintegrator.distributedpath.directsampleall': 'true',
2348 'sintegrator.distributedpath.indirectdiffuse': 'true',
2349 'sintegrator.distributedpath.specularreflectdepth': 3,
2350 'sintegrator.distributedpath.diffusereflectsamples': 1,
2351 'sintegrator.distributedpath.glossyreflectsamples': 1,
2352 'sintegrator.distributedpath.glossyrefractdepth': 5,
2353 'sintegrator.distributedpath.diffusereflectdepth': '2',
2354 'sintegrator.distributedpath.indirectsamples': 1,
2355 'sintegrator.distributedpath.indirectsampleall': 'false',
2356 'sintegrator.distributedpath.glossyrefractsamples': 1,
2357 'sintegrator.distributedpath.directdiffuse': 'true',
2358 'sintegrator.distributedpath.directglossy': 'true',
2359 'sintegrator.distributedpath.strategy': 'auto',
2360 'sintegrator.distributedpath.specularrefractdepth': 5,
2362 'pixelfilter.type': 'mitchell',
2363 'pixelfilter.mitchell.sharp': 0.3333,
2364 'pixelfilter.mitchell.xwidth': 1.5,
2365 'pixelfilter.mitchell.ywidth': 1.5,
2366 'pixelfilter.mitchell.supersample': "true",
2367 'pixelfilter.mitchell.optmode': "slider" }
2369 presets['D Anim - Distributed/GI high Q'] = {
2370 'film.displayinterval': 8,
2373 'useparamkeys': 'false',
2374 'sampler.showadvanced': 'false',
2375 'sintegrator.showadvanced': 'false',
2376 'pixelfilter.showadvanced': 'false',
2378 'sampler.type': 'lowdiscrepancy',
2379 'sampler.lowdisc.pixelsamples': 256,
2380 'sampler.lowdisc.pixelsampler': 'hilbert',
2382 'sintegrator.type': 'distributedpath',
2383 'sintegrator.distributedpath.causticsonglossy': 'true',
2384 'sintegrator.distributedpath.diffuserefractdepth': 5,
2385 'sintegrator.distributedpath.indirectglossy': 'true',
2386 'sintegrator.distributedpath.directsamples': 1,
2387 'sintegrator.distributedpath.diffuserefractsamples': 1,
2388 'sintegrator.distributedpath.glossyreflectdepth': 2,
2389 'sintegrator.distributedpath.causticsondiffuse': 'false',
2390 'sintegrator.distributedpath.directsampleall': 'true',
2391 'sintegrator.distributedpath.indirectdiffuse': 'true',
2392 'sintegrator.distributedpath.specularreflectdepth': 3,
2393 'sintegrator.distributedpath.diffusereflectsamples': 1,
2394 'sintegrator.distributedpath.glossyreflectsamples': 1,
2395 'sintegrator.distributedpath.glossyrefractdepth': 5,
2396 'sintegrator.distributedpath.diffusereflectdepth': '2',
2397 'sintegrator.distributedpath.indirectsamples': 1,
2398 'sintegrator.distributedpath.indirectsampleall': 'false',
2399 'sintegrator.distributedpath.glossyrefractsamples': 1,
2400 'sintegrator.distributedpath.directdiffuse': 'true',
2401 'sintegrator.distributedpath.directglossy': 'true',
2402 'sintegrator.distributedpath.strategy': 'auto',
2403 'sintegrator.distributedpath.specularrefractdepth': 5,
2405 'pixelfilter.type': 'mitchell',
2406 'pixelfilter.mitchell.sharp': 0.3333,
2407 'pixelfilter.mitchell.xwidth': 1.5,
2408 'pixelfilter.mitchell.ywidth': 1.5,
2409 'pixelfilter.mitchell.supersample': "true",
2410 'pixelfilter.mitchell.optmode': "slider" }
2412 presets['E Anim - Distributed/GI very high Q'] = {
2413 'film.displayinterval': 8,
2416 'useparamkeys': 'false',
2417 'sampler.showadvanced': 'false',
2418 'sintegrator.showadvanced': 'false',
2419 'pixelfilter.showadvanced': 'false',
2421 'sampler.type': 'lowdiscrepancy',
2422 'sampler.lowdisc.pixelsamples': 512,
2423 'sampler.lowdisc.pixelsampler': 'hilbert',
2425 'sintegrator.type': 'distributedpath',
2426 'sintegrator.distributedpath.causticsonglossy': 'true',
2427 'sintegrator.distributedpath.diffuserefractdepth': 5,
2428 'sintegrator.distributedpath.indirectglossy': 'true',
2429 'sintegrator.distributedpath.directsamples': 1,
2430 'sintegrator.distributedpath.diffuserefractsamples': 1,
2431 'sintegrator.distributedpath.glossyreflectdepth': 2,
2432 'sintegrator.distributedpath.causticsondiffuse': 'false',
2433 'sintegrator.distributedpath.directsampleall': 'true',
2434 'sintegrator.distributedpath.indirectdiffuse': 'true',
2435 'sintegrator.distributedpath.specularreflectdepth': 3,
2436 'sintegrator.distributedpath.diffusereflectsamples': 1,
2437 'sintegrator.distributedpath.glossyreflectsamples': 1,
2438 'sintegrator.distributedpath.glossyrefractdepth': 5,
2439 'sintegrator.distributedpath.diffusereflectdepth': '2',
2440 'sintegrator.distributedpath.indirectsamples': 1,
2441 'sintegrator.distributedpath.indirectsampleall': 'false',
2442 'sintegrator.distributedpath.glossyrefractsamples': 1,
2443 'sintegrator.distributedpath.directdiffuse': 'true',
2444 'sintegrator.distributedpath.directglossy': 'true',
2445 'sintegrator.distributedpath.strategy': 'auto',
2446 'sintegrator.distributedpath.specularrefractdepth': 5,
2448 'pixelfilter.type': 'mitchell',
2449 'pixelfilter.mitchell.sharp': 0.3333,
2450 'pixelfilter.mitchell.xwidth': 1.5,
2451 'pixelfilter.mitchell.ywidth': 1.5,
2452 'pixelfilter.mitchell.supersample': "true",
2453 'pixelfilter.mitchell.optmode': "slider" }
2457 def getMaterialPresets():
2458 return getPresets('luxblend_materials')
2460 def savePreset(key, name, d):
2462 presets = getPresets(key)
2464 presets[name] = d.copy()
2467 Blender.Registry.SetKey(key, presets, True)
2469 def saveScenePreset(name, d):
2471 for n in presetsExclude:
2474 savePreset('luxblend_presets', name, d)
2476 def saveMaterialPreset(name, d):
2478 for n in presetsExclude:
2481 savePreset('luxblend_materials', name, d)
2485 # **************************************************
2491 usedproperties = {} # global variable to collect used properties for storing presets
2492 usedpropertiesfilterobj = None # assign a object to only collect the properties that are assigned to this object
2494 # class to access properties (for lux settings)
2496 def __init__(self, obj, name, default):
2499 # if len(name)>31: print("Warning: property-name \"%s\" has more than 31 chars."%(name))
2500 self.hashmode = len(name)>31 # activate hash mode for keynames longer 31 chars (limited by blenders ID-prop)
2501 self.hashname = "__hash:%x"%(name.__hash__())
2502 self.default = default
2503 def parseassignment(self, s, name):
2505 if l[0] != name: print("Warning: property-name \"%s\" has hash-collide with \"%s\"."%(name, l[0]))
2507 def createassignment(self, name, value):
2508 return "%s = %s"%(name, value)
2510 global usedproperties, usedpropertiesfilterobj, luxdefaults
2513 value = self.obj.properties['luxblend'][self.name]
2514 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
2515 usedproperties[self.name] = value
2519 value = self.parseassignment(self.obj.properties['luxblend'][self.hashname], self.name)
2520 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
2521 usedproperties[self.name] = value
2524 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
2526 value = luxdefaults[self.name]
2527 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
2528 usedproperties[self.name] = value
2531 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
2532 usedproperties[self.name] = self.default
2534 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
2535 usedproperties[self.name] = self.default
2548 def set(self, value):
2549 global newluxdefaults
2551 if self.hashmode: n, v = self.hashname, self.createassignment(self.name, value)
2552 else: n, v = self.name, value
2553 if value is not None:
2554 try: self.obj.properties['luxblend'][n] = v
2555 except (KeyError, TypeError):
2556 self.obj.properties['luxblend'] = {}
2557 self.obj.properties['luxblend'][n] = v
2559 try: del self.obj.properties['luxblend'][n]
2561 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
2562 # value has changed, so this are user settings, remove preset reference
2563 if not(self.name in defaultsExclude):
2564 newluxdefaults[self.name] = value
2565 try: self.obj.properties['luxblend']['preset']=""
2569 try: del self.obj.properties['luxblend'][self.name]
2571 try: del self.obj.properties['luxblend'][self.hashname]
2575 if type(v) == types.FloatType: return float(v)
2577 if type(v) == types.StringType: return float(v.split(" ")[0])
2580 if type(v) == types.FloatType: return float(v)
2582 if type(v) == types.StringType: return float(v.split(" ")[0])
2586 try: return int(self.get())
2587 except: return int(self.default)
2589 return self.getVector()
2590 def getVector(self):
2592 if type(v) in [types.FloatType, types.IntType]: return (float(v), float(v), float(v))
2595 if type(v) == types.StringType: l = self.get().split(" ")
2598 if (l==None) or (len(l) != 3): l = self.default.split(" ")
2599 return (float(l[0]), float(l[1]), float(l[2]))
2600 except AttributeError:
2601 return (float(l[0]), float(l[0]), float(l[0]))
2603 def getVectorStr(self):
2604 return "%f %f %f"%self.getVector()
2606 return type(self.get()) == types.FloatType
2609 return "%f %f %f"%(rg(col[0]), rg(col[1]),rg(col[2]))
2610 def setRGB(self, value):
2611 self.set("%f %f %f"%(value[0], value[1], value[2]))
2612 def setVector(self, value):
2613 self.set("%f %f %f"%(value[0], value[1], value[2]))
2616 # class to access blender attributes (for lux settings)
2618 def __init__(self, obj, name):
2623 return getattr(self.obj, self.name)
2627 return float(self.get())
2629 return int(self.get())
2640 def set(self, value):
2642 setattr(self.obj, self.name, value)
2646 # class for dynamic gui
2648 def __init__(self, y=200):
2649 self.x = 110 # left start position after captions
2650 self.xmax = 110+2*(140+4)
2652 self.w = 140 # default element width in pixels
2653 self.h = 18 # default element height in pixels
2657 self.resethmax = False
2658 def getRect(self, wu, hu):
2659 w = int(self.w * wu + self.xgap * (wu-1))
2660 h = int(self.h * hu + self.ygap * (hu-1))
2661 if self.x + w > self.xmax: self.newline()
2662 if self.resethmax: self.hmax = 0; self.resethmax = False
2663 rect = [int(self.x), int(self.y-h), int(w), int(h)]
2664 self.x += int(w + self.xgap)
2665 if h+self.ygap > self.hmax: self.hmax = int(h+self.ygap)
2667 def newline(self, title="", distance=0, level=0, icon=None, color=None):
2669 if not(self.resethmax): self.y -= int(self.hmax + distance)
2670 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)
2671 if icon!=None: drawIcon(icon, 2+level*10, self.y-16)
2672 self.resethmax = True
2675 BGL.glColor3f(0.9,0.9,0.9); BGL.glRasterPos2i(20+level*10,self.y-self.h+5); Draw.Text(title)
2677 def luxHelp(name, lux, caption, hint, gui, width=1.0):
2679 r = gui.getRect(width, 1)
2680 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)]))
2681 drawIcon(icon_help, r[0], r[1])
2683 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2685 # lux parameter types
2686 def luxOption(name, lux, options, caption, hint, gui, width=1.0):
2688 menustr = caption+": %t"
2689 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2691 i = options.index(lux.get())
2694 lux.set(lux.default) # not found, so try default value
2695 i = options.index(lux.get())
2697 print("value %s not found in options list"%(lux.get()))
2699 r = gui.getRect(width, 1)
2700 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], i, hint, lambda e,v: lux.set(options[v]))
2701 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2703 def luxOptionRect(name, lux, options, caption, hint, gui, x, y, xx, yy):
2705 menustr = caption+": %t"
2706 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2708 i = options.index(lux.get())
2711 lux.set(lux.default) # not found, so try default value
2712 i = options.index(lux.get())
2714 print ("value %s not found in options list"%(lux.get()))
2716 Draw.Menu(menustr, evtLuxGui, x, y, xx, yy, i, hint, lambda e,v: lux.set(options[v]))
2717 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2719 def luxIdentifier(name, lux, options, caption, hint, gui, icon=None, width=1.0):
2720 if gui: gui.newline(caption+":", 8, 0, icon, [0.75,0.5,0.25])
2721 luxOption(name, lux, options, caption, hint, gui, width)
2722 return "\n%s \"%s\""%(name, lux.get())
2724 def luxFloat(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2726 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2727 r = gui.getRect(width-0.12, 1)
2729 r = gui.getRect(width, 1)
2733 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2735 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2736 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2739 keyname = lux.getname()
2741 useipo = luxProp(obj, keyname+".IPOuse", "false")
2742 i = gui.getRect(0.12, 1)
2743 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)]))
2745 if useipo.get() == "true":
2746 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2747 curve = luxProp(obj, keyname+".IPOCurveName", "")
2748 if curve.get() == "":
2749 c = gui.getRect(2.0, 1)
2751 c = gui.getRect(1.1, 1)
2753 Draw.String("Ipo:", evtLuxGui, c[0], c[1], c[2], c[3], curve.get(), 250, "Set IPO Name", lambda e,v: curve.set(v))
2755 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2758 # Apply IPO to value
2759 if curve.get() != "":
2761 ipoob = Blender.Ipo.Get(curve.get())
2765 if curve.get() != "":
2766 names = list([x[0] for x in ipoob.curveConsts.items()])
2767 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2768 luxOption("ipocurve", ipotype, names, "IPO Curve", "Set IPO Curve", gui, 0.6)
2770 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2771 icu_value = icu[Blender.Get('curframe')]
2772 if usemapping.get() == "false": # if true is set during mapping below
2776 m = gui.getRect(0.3, 1)
2777 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)]))
2778 if usemapping.get() == "true":
2779 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2780 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2781 luxFloatNoIPO("ipofmin", fmin, -100, 100, "fmin", "Map minimum value from Curve", gui, 0.5)
2782 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2783 luxFloatNoIPO("ipofmax", fmax, -100, 100, "fmax", "Map maximum value from Curve", gui, 0.5)
2784 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2785 luxFloatNoIPO("ipotmin", tmin, min, max, "tmin", "Map miminum value to", gui, 0.5)
2786 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2787 luxFloatNoIPO("ipotmax", tmax, min, max, "tmax", "Map maximum value to", gui, 0.5)
2789 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2790 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2793 #v = gui.getRect(0.5, 1)
2794 #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)]))
2796 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2798 keyname = lux.getname()
2799 useipo = luxProp(obj, keyname+".IPOuse", "false")
2800 if useipo.get() == "true":
2801 curve = luxProp(obj, keyname+".IPOCurveName", "")
2803 ipoob = Blender.Ipo.Get(curve.get())
2807 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2809 if curve.get() != "":
2810 names = list([x[0] for x in ipoob.curveConsts.items()])
2811 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2813 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2814 icu_value = icu[Blender.Get('curframe')]
2815 if usemapping.get() == "false": # if true is set during mapping below
2818 if usemapping.get() == "true":
2819 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2820 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2821 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2822 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2823 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2824 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2825 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2827 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2829 def luxFloatNoIPO(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2831 r = gui.getRect(width, 1)
2833 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2835 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2836 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2840 def luxInt(name, lux, min, max, caption, hint, gui, width=1.0):
2842 r = gui.getRect(width, 1)
2843 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getInt(), min, max, hint, lambda e,v: lux.set(v))
2844 return "\n \"integer %s\" [%d]"%(name, lux.getInt())
2846 def luxBool(name, lux, caption, hint, gui, width=1.0):
2848 r = gui.getRect(width, 1)
2849 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)]))
2850 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2852 def luxLabel(caption, gui):
2854 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
2857 def luxCollapse(name, lux, caption, hint, gui, width=1.0):
2859 r = gui.getRect(width, 1)
2860 if lux.get() == "true":
2861 drawArrow(arrow_down, r[0]-22, r[1]-2)
2863 drawArrow(arrow_right, r[0]-22, r[1]-2)
2864 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)]))
2865 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2867 def luxString(name, lux, caption, hint, gui, width=1.0):
2869 r = gui.getRect(width, 1)
2870 Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.get(), 250, hint, lambda e,v: lux.set(v))
2871 if lux.get()==lux.default: return ""
2872 else: return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2874 def luxFile(name, lux, caption, hint, gui, width=1.0):
2876 r = gui.getRect(width, 1)
2877 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))
2878 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()))
2879 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(luxFilePath(lux.get())))
2881 def luxPath(name, lux, caption, hint, gui, width=1.0):
2883 r = gui.getRect(width, 1)
2884 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))
2885 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()))
2886 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2888 def luxRGB(name, lux, max, caption, hint, gui, width=2.0):
2890 r = gui.getRect(width, 1)
2895 if rgb[i] > scale: scale = rgb[i]
2896 rgb = (rgb[0]/scale, rgb[1]/scale, rgb[2]/scale)
2897 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)))
2898 w = int((r[2]-r[3])/3); m = max
2900 w = int((r[2]-r[3])/4); m = 1.0
2901 drawR, drawG, drawB, drawS = Draw.Create(rgb[0]), Draw.Create(rgb[1]), Draw.Create(rgb[2]), Draw.Create(scale)
2902 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)))
2903 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)))
2904 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)))
2906 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)))
2908 return "\n \"color %s\" [%s]"%(name, lux.getRGC())
2909 return "\n \"color %s\" [%s]"%(name, lux.get())
2911 def luxVector(name, lux, min, max, caption, hint, gui, width=2.0):
2913 r = gui.getRect(width, 1)
2914 vec = lux.getVector()
2916 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2917 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)))
2918 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)))
2919 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)))
2920 return "\n \"vector %s\" [%s]"%(name, lux.get())
2922 def luxVectorUniform(name, lux, min, max, caption, hint, gui, width=2.0):
2923 def setUniform(lux, value):
2924 if value: lux.set(lux.getFloat())
2925 else: lux.setVector(lux.getVector())
2927 r = gui.getRect(width, 1)
2928 vec = lux.getVector()
2929 Draw.Toggle("U", evtLuxGui, r[0], r[1], gui.h, gui.h, lux.isFloat(), "uniform", lambda e,v: setUniform(lux, v))
2931 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))
2933 w = int((r[2]-gui.h)/3)
2934 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2935 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)))
2936 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)))
2937 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)))
2938 return "\n \"vector %s\" [%s]"%(name, lux.getVectorStr())
2940 # property translator for lux<->blender camera types
2941 class luxCameraLinker:
2942 def __init__(self, cam, luxCams, blendCams):
2943 self.id = luxProp(cam, 'camera.type.id', 0)
2944 self.prop = luxProp(cam, 'camera.type', 'perspective')
2946 self.default = cam.type
2947 self.luxCams = luxCams
2948 self.blendCams = blendCams
2950 if self.blendCams[self.id.get()] is None:
2951 n = self.luxCams[self.id.get()]
2953 n = self.luxCams[self.blendCams.index(self.cam.type)]
2956 def set(self, value):
2957 self.id.set(self.luxCams.index(value))
2959 self.cam.type = self.blendCams[self.luxCams.index(value)]
2962 self.prop.set(value)
2965 # lux individual identifiers
2966 def luxCamera(cam, context, gui=None):
2967 global icon_c_camera
2970 camtype = luxProp(cam, "camera.type", "perspective")
2971 # camera types for lux<->blender property linking. make sure the number of elements are equal
2972 camlist = ['perspective', 'orthographic', 'environment']
2973 camvals = ['persp', 'ortho', None]
2974 # Radiance - remarked 'realistic' for v0.6 release
2975 #str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment","realistic"], "CAMERA", "select camera type", gui, icon_c_camera)
2976 str = luxIdentifier("Camera", luxCameraLinker(cam, camlist, camvals), camlist, "CAMERA", "select camera type", gui, icon_c_camera)
2979 if camtype.get() == "perspective":
2980 if gui: gui.newline(" View:")
2981 str += luxFloat("fov", luxAttr(cam, "angle"), 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2982 fl = luxAttr(cam, "lens")
2984 luxFloat("lens", fl, 1.0, 250.0, "focallength", "camera focal length", gui)
2986 if camtype.get() == "orthographic" :
2987 str += luxFloat("scale", luxAttr(cam, "scale"), 0.01, 1000.0, "scale", "orthographic camera scale", gui)
2988 scale = cam.scale / 2
2990 if camtype.get() == "realistic":
2991 if gui: gui.newline(" View:")
2992 fov = luxAttr(cam, "angle")
2993 str += luxFloat("fov", fov, 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2994 if gui: luxFloat("lens", luxAttr(cam, "lens"), 1.0, 250.0, "focallength", "camera focal length", gui)
2996 if gui: gui.newline()
2997 str += luxFile("specfile", luxProp(cam, "camera.realistic.specfile", ""), "spec-file", "", gui, 1.0)
2998 # if gui: gui.newline()
2999 # auto calc str += luxFloat("filmdistance", luxProp(cam, "camera.realistic.filmdistance", 70.0), 0.1, 1000.0, "film-dist", "film-distance [mm]", gui)
3000 filmdiag = luxProp(cam, "camera.realistic.filmdiag", 35.0)
3001 str += luxFloat("filmdiag", filmdiag, 0.1, 1000.0, "film-diag", "[mm]", gui)
3002 if gui: gui.newline()
3003 fstop = luxProp(cam, "camera.realistic.fstop", 1.0)
3004 luxFloat("aperture_diameter", fstop, 0.1, 100.0, "f-stop", "", gui)
3005 dofdist = luxAttr(cam, "dofDist")
3006 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)
3008 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
3009 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
3010 focal = filmdiag.get()*0.001 / math.tan(fov.get() * math.pi / 360.0) / 2.0
3011 print("calculated focal length: %f mm"%(focal * 1000.0))
3012 aperture_diameter = focal / fstop.get()
3013 print("calculated aperture diameter: %f mm"%(aperture_diameter * 1000.0))
3014 str += "\n \"float aperture_diameter\" [%f]"%(aperture_diameter*1000.0)
3015 filmdistance = dofdist.get() * focal / (dofdist.get() - focal)
3016 print("calculated film distance: %f mm"%(filmdistance * 1000.0))
3017 str += "\n \"float filmdistance\" [%f]"%(filmdistance*1000.0)
3020 useclip = luxProp(cam, "useclip", "false")
3021 luxCollapse("useclip", useclip, "Near & Far Clipping", "Enable Camera near and far clipping options", gui, 2.0)
3022 if(useclip.get() == "true"):
3023 if gui: gui.newline(" Clipping:")
3024 str += luxFloat("hither", luxAttr(cam, "clipStart"), 0.0, 100.0, "start", "near clip distance", gui)
3025 str += luxFloat("yon", luxAttr(cam, "clipEnd"), 1.0, 10000.0, "end", "far clip distance", gui)
3028 usedof = luxProp(cam, "usedof", "false")
3030 if camtype.get() in ["perspective", "orthographic"]:
3031 luxCollapse("usedof", usedof, "Depth of Field & Bokeh", "Enable Depth of Field & Aperture options", gui, 2.0)
3034 if usedof.get() == "true":
3036 if gui: gui.newline(" DOF:")
3038 lr = luxProp(cam, "camera.lensradius", 0.01)
3039 fs = luxProp(cam, "camera.fstop", 2.8)
3041 if camtype.get() == "perspective":
3043 usefstop = luxProp(cam, "usefstop", "true")
3044 luxBool("usefstop", usefstop, "Use f/stop", "Use f/stop to define DOF effect", gui, 1.0)
3046 LR_SCALE = 1000.0 # lr in metres -> mm
3047 FL_SCALE = 1.0 # fl in mm -> mm
3049 def lr_2_fs(fl, lr):
3051 return fl / ( 2.0 * lr )
3053 def fs_2_lr(fl, fs):
3054 return fl / ( 2.0 * fs )
3056 if usefstop.get() == 'true':
3057 halfstop = luxProp(cam, 'camera.halfstop', 'false')
3058 luxBool('camera.halfstop', halfstop, 'half-stop', 'Use half-stop presets', gui, 0.5)
3059 fs.default = 2.8 if halfstop.get() == 'false' else 3.3
3060 luxOption('camera.fstoppresets', fs, luxFstopPresets('full' if halfstop.get() == 'false' else 'half'), 'f/stop', 'Choose the focal ratio number (lens aperture)', gui, 0.5)
3061 lr.set(fs_2_lr(fl.get() * FL_SCALE, fs.get()) / LR_SCALE)
3062 str += luxFloat("lensradius", lr, 0.0, 1.0, "", "", None)
3064 fs.set(lr_2_fs(fl.get() * FL_SCALE, lr.get() * LR_SCALE))
3065 str += luxFloat("lensradius", lr, 0.0, 1.0, "lens-radius", "Defines the lens radius. Values higher than 0 enable DOF and control its amount", gui)
3067 str += luxFloat("lensradius", lr, 0.0, 1.0, "lens-radius", "Defines the lens radius. Values higher than 0 enable DOF and control its amount", gui)
3069 focustype = luxProp(cam, "camera.focustype", "autofocus")
3070 luxOption("focustype", focustype, ["autofocus", "manual", "object"], "Focus Type", "Choose the focus behaviour", gui)
3073 if focustype.get() == "autofocus":
3074 str += luxBool("autofocus",luxProp(cam, "camera.autofocus", "true"), "autofocus", "Enable automatic focus", gui)
3075 if focustype.get() == "object":
3076 objectfocus = luxProp(cam, "camera.objectfocus", "")
3077 luxString("objectfocus", objectfocus, "object", "Always focus camera on named object", gui, 1.0)
3078 dofdist = luxAttr(cam, "dofDist")
3079 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)
3080 if objectfocus.get() != "":
3082 setFocus(objectfocus.get())
3084 luxProp(cam, "camera.objectfocus", "").set("")
3085 Draw.PupMenu("WARNING: focus-object does not match existing object-name")
3086 if LuxIsGUI: Draw.Redraw()
3088 if focustype.get() == "manual":
3089 dofdist = luxAttr(cam, "dofDist")
3090 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)
3092 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
3093 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
3095 if camtype.get() == "perspective" and usedof.get() == "true":
3096 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)
3097 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)
3098 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)
3100 useaspect = luxProp(cam, "useaspectratio", "false")
3101 aspectratio = luxProp(cam, "ratio", 1.3333)
3102 if camtype.get() in ["perspective", "orthographic"]:
3103 useshift = luxProp(cam, "camera.useshift", "false")
3104 luxCollapse("useshift", useshift, "Architectural (Lens Shift) & Aspect Ratio", "Enable Lens Shift and Aspect Ratio options", gui, 2.0)
3105 if(useshift.get() == "true"):
3106 if gui: gui.newline(" Shift:")
3107 luxFloat("X", luxAttr(cam, "shiftX"), -2.0, 2.0, "X", "horizontal lens shift", gui)
3108 luxFloat("Y", luxAttr(cam, "shiftY"), -2.0, 2.0, "Y", "vertical lens shift", gui)
3110 if gui: gui.newline(" AspectRatio:")
3111 luxBool("useaspectratio", useaspect, "Custom", "Define a custom frame aspect ratio", gui)
3112 if useaspect.get() == "true":
3113 str += luxFloat("frameaspectratio", aspectratio, 0.0001, 3.0, "aspectratio", "Frame aspect ratio", gui)
3115 if useaspect.get() == "true":
3116 ratio = 1./aspectratio.get()
3118 ratio = float(context.sizeY)/float(context.sizeX)
3120 screenwindow = [(2*cam.shiftX-1)*scale, (2*cam.shiftX+1)*scale, (2*cam.shiftY-ratio)*scale, (2*cam.shiftY+ratio)*scale]
3122 screenwindow = [(2*cam.shiftX-1/ratio)*scale, (2*cam.shiftX+1/ratio)*scale, (2*cam.shiftY-1)*scale, (2*cam.shiftY+1)*scale]
3123 # render region option
3124 if context.borderRender:
3125 (x1,y1,x2,y2) = context.border
3126 screenwindow = [screenwindow[0]*(1-x1)+screenwindow[1]*x1, screenwindow[0]*(1-x2)+screenwindow[1]*x2,\
3127 screenwindow[2]*(1-y1)+screenwindow[3]*y1, screenwindow[2]*(1-y2)+screenwindow[3]*y2]
3128 str += "\n \"float screenwindow\" [%f %f %f %f]"%(screenwindow[0], screenwindow[1], screenwindow[2], screenwindow[3])
3130 # Note - radiance - this is a work in progress
3131 # Flash lamp option for perspective and ortho cams
3132 # if camtype.get() in ["perspective", "orthographic"]:
3133 # useflash = luxProp(cam, "useflash", "false")
3134 # luxBool("useflash", useflash, "Flash Lamp", "Enable Camera mounted flash lamp options", gui, 2.0)
3136 # Motion Blur Options (common to all cameras)
3137 usemblur = luxProp(cam, "usemblur", "false")
3138 luxCollapse("usemblur", usemblur, "Motion Blur", "Enable Motion Blur", gui, 2.0)
3139 if(usemblur.get() == "true"):
3140 if gui: gui.newline(" Shutter:")
3141 mblurpreset = luxProp(cam, "mblurpreset", "true")
3142 luxBool("mblurpreset", mblurpreset, "Preset", "Enable use of Shutter Presets", gui, 0.5)
3143 if(mblurpreset.get() == "true"):
3144 mblurpresetstype = luxProp(cam, "mblurpresetstype", 'photo')
3145 luxOption("mblurpresetstype", mblurpresetstype, ['photo', 'cinema'], "camera type", "Choose whether to use still photographic or cinematographic camera presets", gui, 0.5)
3147 shutterpreset = luxProp(cam, "camera.shutterspeedpreset", "1/60" if mblurpresetstype.get() == 'photo' else "180-degree")
3148 luxOption("shutterpreset", shutterpreset, luxShutterSpeedPresets(mblurpresetstype.get()), "shutter speed", "Choose the Shutter speed preset", gui, 0.5 if mblurpresetstype.get() == 'cinema' else 1.0)
3150 shutfps = luxProp(cam, "camera.shutfps", "25 FPS")
3151 if mblurpresetstype.get() == 'cinema':
3152 luxOption("shutfps", shutfps, luxFPSPresets(), "@", "Choose the number of frames per second as the time base", gui, 0.5)
3154 str += "\n \"float shutteropen\" [%f]\n \"float shutterclose\" [%f] " % (0, luxFilmExposure(mblurpresetstype.get(), shutterpreset.get(), shutfps.get()))
3157 str += luxFloat("shutteropen", luxProp(cam, "camera.shutteropen", 0.0), 0.0, 100.0, "open", "time in seconds when shutter opens", gui, 0.75)
3158 str += luxFloat("shutterclose", luxProp(cam, "camera.shutterclose", 1.0), 0.0, 100.0, "close", "time in seconds when shutter closes", gui, 0.75)
3160 str += luxOption("shutterdistribution", luxProp(cam, "camera.shutterdistribution", "gaussian"), ["uniform", "gaussian"], "distribution", "Choose the shutter sampling distribution", gui, 2.0)
3161 objectmblur = luxProp(cam, "objectmblur", "true")
3162 luxBool("objectmblur", objectmblur, "Object", "Enable Motion Blur for scene object motions", gui, 1.0)
3163 cammblur = luxProp(cam, "cammblur", "true")
3164 luxBool("cammblur", cammblur, "Camera", "Enable Motion Blur for Camera motion", gui, 1.0)
3168 def luxFPSPresets():
3169 return ['10 FPS', '12 FPS', '20 FPS', '24 FPS', '25 FPS', '29.976 FPS', '30 FPS', '50 FPS', '60 FPS', '100 FPS', '200 FPS', '500 FPS']
3171 def luxISOPresets():
3172 return [20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000]
3174 def luxShutterSpeedPresets(type):
3176 'photo': ['1', '1/2', '1/4', '1/8', '1/15', '1/30', '1/60', '1/125', '1/250', '1/500', '1/1000'],
3177 'cinema': ['45-degree', '90-degree', '180-degree', '270-degree']
3181 def luxFstopPresets(type):
3183 'full': [0.5, 0.7, 1, 1.4, 2, 2.8, 4, 5.6, 8, 11, 16, 22, 32, 45, 64, 90, 128],
3184 'half': [1.2, 1.7, 2.4, 3.3, 4.8, 6.7, 9.5, 13, 19, 27, 38, 54, 77, 109]
3188 def luxFilmExposure(type, shutterStr, fpsStr):
3189 if type == 'photo': fps = 1
3190 else: fps = float(fpsStr[:fpsStr.find(' ')]) # assuming fps are in form 'n FPS'
3192 if shutterStr == '1': exp = 1.0
3193 elif type == 'photo': exp = 1.0 / float(shutterStr[2:]) # assuming still camera shutterspeed is in form '1/n'
3194 elif type == 'cinema': exp = (1.0/fps) * (1-float(shutterStr[:shutterStr.find('-')])/360) # assuming motion camera shutterspeed is in form 'n-degree'
3197 def get_render_resolution(scn, gui = None):
3198 context = scn.getRenderingContext()
3199 scale = luxProp(scn, "film.scale", "100 %")
3200 scale = int(scale.get()[:-1])
3201 xr = luxAttr(context, "sizeX").get()*scale/100
3202 yr = luxAttr(context, "sizeY").get()*scale/100
3206 def borderResize(scn, xr, yr):
3207 # update border region dimensions
3209 context = scn.getRenderingContext()
3210 t = (yr - luxProp(scn, "film.border.T", yr-yr*context.border[3]).get()) / float(yr)
3211 l = luxProp(scn, "film.border.L", xr*context.border[0]).get() / float(xr)
3212 b = (yr - luxProp(scn, "film.border.B", yr-yr*context.border[1]).get()) / float(yr)
3213 r = luxProp(scn, "film.border.R", xr*context.border[2]).get() / float(xr)
3214 luxProp(scn, "film.border.T", 0).delete()
3215 luxProp(scn, "film.border.L", 0).delete()
3216 luxProp(scn, "film.border.B", yr).delete()
3217 luxProp(scn, "film.border.R", xr).delete()
3218 context.setBorder(l, b, r, t)
3220 def borderAspectReset(scn, xr, yr):
3221 # recalculate border region coordinates according to the image
3222 # aspect ratio. resize the region relative to its center.
3224 context = scn.getRenderingContext()
3225 # unpack border proportions
3226 (l, b, r, t) = context.border
3227 # recalculate border edges pixel positions relative to image's left/top
3232 # border region width/height
3235 # center of the border region (relative to the image)
3238 # image aspect ratio
3239 aspect = float(xr) / float(yr)
3240 # calculate new dimensions for the border region. silly ugly code -__-
3243 nh = (w>h and w or h) / aspect
3246 nh = (w<h and w or h) / aspect
3247 # set new border edges pixel positions from the region's
3248 # center and move it if we got out off the image boundaries
3266 luxProp(scn, "film.border.T", nt).set(nt)
3267 luxProp(scn, "film.border.L", nl).set(nl)
3268 luxProp(scn, "film.border.B", nb).set(nb)
3269 luxProp(scn, "film.border.R", nr).set(nr)
3270 borderResize(scn, xr, yr)
3272 def luxFilm(scn, gui=None):
3275 filmtype = luxProp(scn, "film.type", "fleximage")
3276 str = luxIdentifier("Film", filmtype, ["fleximage"], "FILM", "select film type", gui)
3277 if filmtype.get() == "fleximage":
3278 context = scn.getRenderingContext()
3280 if gui: gui.newline(" Resolution:")
3282 xr,yr = get_render_resolution(scn, gui)
3284 luxInt("xresolution", luxAttr(context, "sizeX"), 0, 8192, "X", "width of the render", gui, 0.666)
3285 luxInt("yresolution", luxAttr(context, "sizeY"), 0, 8192, "Y", "height of the render", gui, 0.666)
3286 scale = luxProp(scn, "film.scale", "100 %")
3287 luxOption("", scale, ["400 %", "200 %", "100 %", "75 %", "50 %", "25 %"], "scale", "scale resolution", gui, 0.666)
3289 # render region option
3290 if context.borderRender:
3291 if gui: gui.newline(" Border:")
3292 borderzoom = luxProp(scn, "film.border.zoom", "false")
3293 luxBool("borderzoom", borderzoom, "Zoom", "Zoom in to the border region", gui, borderzoom.get() == "true" and 1.0 or 2.0)
3294 if borderzoom.get() == "true" and gui:
3295 r = gui.getRect(1, 1)
3296 Draw.Button("aspect ratio", evtLuxGui, r[0], r[1], r[2], r[3], "Reset border dimensions to the image aspect ratio (relative to the region center)", lambda e,v: borderAspectReset(scn,xr,yr))
3298 borderprecise = luxProp(scn, "film.border.precise", "false")
3299 luxCollapse("borderprecise", borderprecise, "Precise border dimensions", "Manually configure border region dimensions", gui, 2.0)
3300 if borderprecise.get() == "true" and gui:
3301 luxInt("borderleft", luxProp(scn, "film.border.L", xr*context.border[0]), 0, xr*context.border[2], "L", "Left edge of the border region", gui, 0.5)
3302 luxInt("borderright", luxProp(scn, "film.border.R", xr*context.border[2]), xr*context.border[0], xr, "R", "Right edge of the border region", gui, 0.5)
3303 luxInt("bordertop", luxProp(scn, "film.border.T", yr-yr*context.border[3]), 0, yr-yr*context.border[1], "T", "Top edge of the border region", gui, 0.5)
3304 luxInt("borderbottom", luxProp(scn, "film.border.B", yr-yr*context.border[1]), yr-yr*context.border[3], yr, "B", "Bottom edge of the border region", gui, 0.5)
3305 borderResize(scn,xr,yr)
3307 (x1,y1,x2,y2) = context.border
3308 if (x1==x2) or (y1==y2): print("WARNING: Empty render region, use SHIFT-B to set render region in Blender.")
3309 if borderzoom.get() != "true":
3312 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(w, h)
3316 aspect = float(xr>yr and xr or yr) / float(w>h and w or h)
3319 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(w, h)
3321 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(xr, yr)
3322 luxProp(scn, "film.border.T", 0).delete()
3323 luxProp(scn, "film.border.L", 0).delete()
3324 luxProp(scn, "film.border.B", yr).delete()
3325 luxProp(scn, "film.border.R", xr).delete()
3327 if gui: gui.newline(" Output:")
3328 str += luxInt("displayinterval", luxProp(scn, "film.displayinterval", 12), 4, 3600, "display interval", "Set display interval (seconds)", gui)
3329 str += luxInt("writeinterval", luxProp(scn, "film.writeinterval", 120), 12, 3600, "write interval", "Set display interval (seconds)", gui)
3331 if gui: gui.newline(" Halt:")
3332 if luxProp(scn, 'useparamkeys', 'false').get() == 'false':
3333 str += luxInt("haltspp", luxProp(scn, "haltspp", 0), 0, 32768, "halt at spp", "Stop rendering after specified amount of samples per pixel (0 = never halt)", gui)
3334 str += luxInt("halttime", luxProp(scn, "halttime", 0), 0, 86400, "halt at time", "Stop rendering after specified number of seconds (0 = never halt)", gui)
3336 haltspp = luxProp(scn, 'haltspp', 0)
3337 halttime = luxProp(scn, 'halttime', 0)
3338 luxFloat("haltspp", haltspp, 0, 32768.0, "halt at spp", "Stop rendering after specified amount of samples per pixel (0 = never halt)", gui)
3339 luxFloat("halttime", halttime, 0, 86400.0, "halt at time", "Stop rendering after specified number of seconds (0 = never halt)", gui)
3340 haltspp.set(math.ceil(float(haltspp.get())))
3341 halttime.set(math.ceil(float(halttime.get())))
3342 str += luxInt('haltspp', haltspp, 0, 32768, '', '', None)
3343 str += luxInt('halttime', halttime, 0, 86400, '', '', None)
3345 if gui: gui.newline(" Tonemap:")
3346 tonemapkernel = luxProp(scn, "film.tonemapkernel", "reinhard")
3347 str += luxOption("tonemapkernel", tonemapkernel, ["reinhard", "linear", "contrast", "maxwhite"], "Tonemapping Kernel", "Select the tonemapping kernel to use", gui, 1.2)
3348 str += luxBool("premultiplyalpha", luxProp(scn, "film.premultiplyalpha", "false"), "Premultiply Alpha", "Premultiply film alpha channel during normalization", gui, 0.8)
3349 if tonemapkernel.get() == "reinhard":
3350 str += luxFloat("reinhard_prescale", luxProp(scn, "film.reinhard.prescale", 1.0), 0.0, 10.0, "preScale", "Image scale before tonemap operator", gui)
3351 str += luxFloat("reinhard_postscale", luxProp(scn, "film.reinhard.postscale", 1.2), 0.0, 10.0, "postScale", "Image scale after tonemap operator", gui)
3352 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, 2.0)
3353 elif tonemapkernel.get() == "linear":
3354 linearSensitivity = luxProp(scn, 'film.linear.sensitivity', 100.0)
3355 linearExposure = luxProp(scn, 'film.linear.exposure', 0.008)
3356 linearFstop = luxProp(scn, 'film.linear.fstop', 2.8)
3357 linearPreset = luxProp(scn, 'film.linear.presets', 'true')
3358 luxBool('linearpresets', linearPreset, 'Preset', 'Enable use of lens and film presets', gui, 0.5 if linearPreset.get() == 'true' else 1.0)
3359 if linearPreset.get() == 'true':
3360 linearPresetsType = luxProp(scn, 'film.linear.cameratype', 'photo')
3361 luxOption('linearpresetstype', linearPresetsType, ['photo', 'cinema'], 'camera type', 'Choose whether to use still photographic or cinematographic camera presets', gui, 0.5)
3362 linearExposurePreset = luxProp(scn, 'film.linear.exposurepreset', '1/125' if linearPresetsType.get() == 'photo' else '180-degree')
3363 luxOption('linearexposurepreset', linearExposurePreset, luxShutterSpeedPresets(linearPresetsType.get()), 'exposure', 'Exposure duration in seconds, or shutter speed', gui, 0.5 if linearPresetsType.get() == 'cinema' else 1.0)
3364 linearFPSPreset = luxProp(scn, 'film.linear.camerafps', '25 FPS')
3365 if linearPresetsType.get() == 'cinema':
3366 luxOption('linearfpspreset', linearFPSPreset, luxFPSPresets(), '@', 'Choose the number of frames per second as the time base', gui, 0.5)
3367 linearExposure.set(luxFilmExposure(linearPresetsType.get(), linearExposurePreset.get(), linearFPSPreset.get()))
3368 linearHalfStop = luxProp(scn, 'film.linear.halfstop', 'false')
3369 luxBool('linearhalfstop', linearHalfStop, 'half-stop', 'Use half-stop presets', gui, 0.5)
3370 linearFstop.default = 2.8 if linearHalfStop.get() == 'false' else 3.3
3371 luxOption('linearpresetsfstop', linearFstop, luxFstopPresets('full' if linearHalfStop.get() == 'false' else 'half'), 'f/stop', 'Choose the focal ratio number (lens aperture)', gui, 0.5)
3372 linearFstop.set(float(linearFstop.get()))
3373 luxOption('linearpresetsiso', linearSensitivity, luxISOPresets(), 'film ISO', 'Choose film sensitivity (ISO scale number)', gui)
3374 linearSensitivity.set(float(linearSensitivity.get()))
3378 str += luxFloat("linear_sensitivity", linearSensitivity, 1.0, 1000.0, "sensitivity", "Film adaption/sensitivity", linearGUI)
3379 str += luxFloat("linear_exposure", linearExposure, 0.0001, 1.0, "exposure", "Exposure duration in seconds", linearGUI)
3380 str += luxFloat("linear_fstop", linearFstop, 0.1, 128.0, "f/stop", "Focal ratio number", linearGUI)
3381 str += luxFloat("linear_gamma", luxProp(scn, "film.gamma", 2.2), 0.0, 8.0, "gamma", "Film gamma correction", None)
3382 elif tonemapkernel.get() == "contrast":
3383 str += luxFloat("contrast_ywa", luxProp(scn, "film.contrast.ywa", 0.1), 0.001, 10000.0, "Ywa", "Display/World Adaption Luminance", gui, 2.0)
3385 # Image File Outputs
3387 # LDR clamping method
3388 if gui: gui.newline(" Clamping:")
3389 ldrclampmethod = luxProp(scn, "film.ldr_clamp_method", "lum")
3390 str += luxOption("ldr_clamp_method", ldrclampmethod, ["lum", "hue", "cut"], "LDR clamping", "Method to clamp high luminance values for LDR output", gui, 0.5)
3391 if gui: gui.newline()
3394 if gui: gui.newline(" OpenEXR:")
3395 saveexr = luxProp(scn, "film.write_exr", "false")
3396 str += luxCollapse("write_exr", saveexr, "OpenEXR Output", "Enable OpenEXR output", gui, 2.0)
3398 if saveexr.get() == "true":
3399 exrchannels = luxProp(scn, "film.write_exr_channels", "RGBA")
3400 str += luxOption("write_exr_channels", exrchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
3401 exrres = luxProp(scn, "film.write_exr_halftype", "true")
3402 str += luxBool("write_exr_halftype", exrres, "16bit Half", "Enable 16bit Half resolution output, otherwise 32bit float", gui, 0.5)
3403 exrcompression = luxProp(scn, "film.write_exr_compression", "PIZ (lossless)")
3404 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)
3406 exrimaging = luxProp(scn, "film.write_exr_imaging", "true")
3407 str += luxBool("write_exr_applyimaging", exrimaging, "Apply Imaging/Tonemapping", "Apply Imaging and Tonemapping pipeline", gui, 1.2)
3409 if exrimaging.get()=="true":
3410 exrgamutclamp = luxProp(scn, "film.write_exr_gamutclamp", "true")
3411 str += luxBool("write_exr_gamutclamp", exrgamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 0.8)
3413 if gui: gui.newline()
3415 exrZ = luxProp(scn, "film.write_exr_Z", "true")
3416 str += luxBool("write_exr_ZBuf", exrZ, "ZBuf", "Enable Z Depth Buffer channel", gui, 0.8)
3417 if exrZ.get() == "true":
3418 exrZNormalize = luxProp(scn, "film.write_exr_ZNorm", "None")
3419 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)
3422 if gui: gui.newline(" PNG:")
3423 savepng = luxProp(scn, "film.write_png", "true")
3424 str += luxCollapse("write_png", savepng, "PNG Output", "Enable PNG (Portable Network Graphics) output", gui, 2.0)
3426 if savepng.get() == "true":
3427 pngchannels = luxProp(scn, "film.write_png_channels", "RGB")
3428 str += luxOption("write_png_channels", pngchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
3429 png16bit = luxProp(scn, "film.write_png_16bit", "false")
3430 str += luxBool("write_png_16bit", png16bit, "16bit", "Enable 16bits per channel resolution PNG output", gui, 0.5)
3431 pnggamutclamp = luxProp(scn, "film.write_png_gamutclamp", "true")
3432 str += luxBool("write_png_gamutclamp", pnggamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.0)
3435 #pngZ = luxProp(scn, "film.write_png_ZBuf", "false")
3436 #str += luxBool("write_png_ZBuf", pngZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
3437 #if pngZ.get() == "true":
3438 # pngZNormalize = luxProp(scn, "film.write_png_ZNorm", "Min/Max")
3439 # 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)
3442 if gui: gui.newline(" TGA:")
3443 savetga = luxProp(scn, "film.write_tga", "false")
3444 str += luxCollapse("write_tga", savetga, "TGA Output", "Enable TGA output", gui, 2.0)
3446 if savetga.get() == "true":
3447 tgachannels = luxProp(scn, "film.write_tga_channels", "RGB")
3448 str += luxOption("write_tga_channels", tgachannels, ["Y", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
3449 tgagamutclamp = luxProp(scn, "film.write_tga_gamutclamp", "true")
3450 str += luxBool("write_tga_gamutclamp", tgagamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.5)
3453 #tgaZ = luxProp(scn, "film.write_tga_ZBuf", "false")
3454 #str += luxBool("write_tga_ZBuf", tgaZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
3455 #if tgaZ.get() == "true":
3456 # tgaZNormalize = luxProp(scn, "film.write_tga_ZNorm", "Min/Max")
3457 # 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)
3460 # override output image dir in case of command line batch mode
3461 overrideop = luxProp(scn, "overrideoutputpath", "")
3462 if overrideop.get() != "":
3463 filebase = os.path.splitext(os.path.basename(Blender.Get('filename')))[0]
3464 filename = overrideop.get() + "/" + filebase + "-%05d" % (Blender.Get('curframe'))
3465 str += "\n \"string filename\" [\"%s\"]"%(filename)
3467 fn = luxProp(scn, "filename", "default-%05d" % (Blender.Get('curframe')))
3468 str += "\n \"string filename\" [\"%s\"]" % luxstr(luxFilePath(fn.get()))
3470 if gui: gui.newline(" Resume:")
3471 resumeflm = luxProp(scn, "film.write_resume_flm", "false")
3472 str += luxBool("write_resume_flm", resumeflm, "Write/Use FLM", "Write a resume fleximage .flm file, or resume rendering if it already exists", gui)
3473 restartflm = luxProp(scn, "film.restart_resume_flm", "true")
3474 str += luxBool("restart_resume_flm", restartflm, "Restart/Erase", "Restart with a black flm, even it a previous flm exists", gui)
3475 if gui: gui.newline(" Reject:")
3476 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)
3477 debugmode = luxProp(scn, "film.debug", "false")
3478 str += luxBool("debug", debugmode, "debug", "Turn on debug reporting and switch off reject", gui)
3481 if gui: gui.newline(" Colorspace:")
3483 cspaceusepreset = luxProp(scn, "film.colorspaceusepreset", "true")
3484 luxBool("colorspaceusepreset", cspaceusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
3486 # Default values for 'sRGB - HDTV (ITU-R BT.709-5)'
3487 cspacewhiteX = luxProp(scn, "film.cspacewhiteX", 0.314275)
3488 cspacewhiteY = luxProp(scn, "film.cspacewhiteY", 0.329411)
3489 cspaceredX = luxProp(scn, "film.cspaceredX", 0.63)
3490 cspaceredY = luxProp(scn, "film.cspaceredY", 0.34)
3491 cspacegreenX = luxProp(scn, "film.cspacegreenX", 0.31)
3492 cspacegreenY = luxProp(scn, "film.cspacegreenY", 0.595)
3493 cspaceblueX = luxProp(scn, "film.cspaceblueX", 0.155)
3494 cspaceblueY = luxProp(scn, "film.cspaceblueY", 0.07)
3495 gamma = luxProp(scn, "film.gamma", 2.2)
3497 if(cspaceusepreset.get() == "true"):
3499 cspace = luxProp(scn, "film.colorspace", "sRGB - HDTV (ITU-R BT.709-5)")
3500 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"]
3501 luxOption("colorspace", cspace, cspaces, "Colorspace", "select output working colorspace", gui, 1.6)
3503 if cspace.get()=="sRGB - HDTV (ITU-R BT.709-5)":
3504 cspacewhiteX.set(0.314275); cspacewhiteY.set(0.329411) # sRGB
3505 cspaceredX.set( 0.63); cspaceredY.set(0.34)
3506 cspacegreenX.set(0.31); cspacegreenY.set(0.595)
3507 cspaceblueX.set(0.155); cspaceblueY.set( 0.07)
3508 elif cspace.get()=="ROMM RGB":
3509 cspacewhiteX.set(0.346); cspacewhiteY.set(0.359) # D50
3510 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
3511 cspacegreenX.set(0.1596); cspacegreenY.set(0.8404)
3512 cspaceblueX.set(0.0366); cspaceblueY.set(0.0001)
3513 elif cspace.get()=="Adobe RGB 98":
3514 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
3515 cspaceredX.set(0.64); cspaceredY.set(0.34)
3516 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
3517 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
3518 elif cspace.get()=="Apple RGB":
3519 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
3520 cspaceredX.set(0.625); cspaceredY.set(0.34)
3521 cspacegreenX.set(0.28); cspacegreenY.set(0.595)
3522 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
3523 elif cspace.get()=="NTSC (FCC 1953, ITU-R BT.470-2 System M)":
3524 cspacewhiteX.set(0.310); cspacewhiteY.set(0.316) # C
3525 cspaceredX.set(0.67); cspaceredY.set(0.33)
3526 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
3527 cspaceblueX.set(0.14); cspaceblueY.set(0.08)
3528 elif cspace.get()=="NTSC (1979) (SMPTE C, SMPTE-RP 145)":
3529 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
3530 cspaceredX.set(0.63); cspaceredY.set(0.34)
3531 cspacegreenX.set(0.31); cspacegreenY.set(0.595)
3532 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
3533 elif cspace.get()=="PAL/SECAM (EBU 3213, ITU-R BT.470-6)":
3534 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
3535 cspaceredX.set(0.64); cspaceredY.set(0.33)
3536 cspacegreenX.set(0.29); cspacegreenY.set(0.60)
3537 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
3538 elif cspace.get()=="CIE (1931) E":
3539 cspacewhiteX.set(0.333); cspacewhiteY.set(0.333) # E
3540 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
3541 cspacegreenX.set(0.2738); cspacegreenY.set(0.7174)
3542 cspaceblueX.set(0.1666); cspaceblueY.set(0.0089)
3544 whitepointusecspace = luxProp(scn, "film.whitepointusecolorspace", "true")
3545 luxBool("whitepointusecolorspace", whitepointusecspace, "Colorspace Whitepoint", "Use default whitepoint for selected colorspace", gui, 1.0)
3546 gammausecspace = luxProp(scn, "film.gammausecolorspace", "true")
3547 luxBool("gammausecolorspace", gammausecspace, "Colorspace Gamma", "Use default output gamma for selected colorspace", gui, 1.0)
3549 if(whitepointusecspace.get() == "false"):
3550 if gui: gui.newline(" Whitepoint:")
3551 whitepointusepreset = luxProp(scn, "film.whitepointusepreset", "true")
3552 luxBool("whitepointusepreset", whitepointusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
3554 if(whitepointusepreset.get() == "true"):
3555 whitepointpresets = ["A - incandescent", "B - sunlight", "C - daylight", "D50 - daylight, 5003K", "D55 - daylight, 5503K", "D65 - daylight, 6504K", "D75 - daylight, 7504K", "E - equal energy", "F2 - standard fluorescent", "F7 - broadband fluorescent", "F11 - narrow threeband fluorescent", "9300"]
3556 whitepointpreset = luxProp(scn, "film.whitepointpreset", "D65 - daylight, 6504K")
3557 luxOption("whitepointpreset", whitepointpreset, whitepointpresets, " PRESET", "select Whitepoint preset", gui, 1.6)
3559 if whitepointpreset.get().startswith("E - "): cspacewhiteX.set(0.333); cspacewhiteY.set(0.333)
3560 elif whitepointpreset.get().startswith("D50 - "): cspacewhiteX.set(0.346); cspacewhiteY.set(0.359)
3561 elif whitepointpreset.get().startswith("D55 - "): cspacewhiteX.set(0.332); cspacewhiteY.set(0.347)
3562 elif whitepointpreset.get().startswith("D65 - "): cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
3563 elif whitepointpreset.get().startswith("D75 - "): cspacewhiteX.set(0.299); cspacewhiteY.set(0.315)
3564 elif whitepointpreset.get().startswith("A - "): cspacewhiteX.set(0.448); cspacewhiteY.set(0.407)
3565 elif whitepointpreset.get().startswith("B - "): cspacewhiteX.set(0.348); cspacewhiteY.set(0.352)
3566 elif whitepointpreset.get().startswith("C - "): cspacewhiteX.set(0.310); cspacewhiteY.set(0.316)
3567 elif whitepointpreset.get().startswith("9300"): cspacewhiteX.set(0.285); cspacewhiteY.set(0.293)
3568 elif whitepointpreset.get().startswith("F2 - "): cspacewhiteX.set(0.372); cspacewhiteY.set(0.375)
3569 elif whitepointpreset.get().startswith("F7 - "): cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
3570 elif whitepointpreset.get().startswith("F11 - "): cspacewhiteX.set(0.381); cspacewhiteY.set(0.377)
3572 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
3573 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
3575 if(gammausecspace.get() == "false"):
3576 if gui: gui.newline(" Gamma:")
3577 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
3580 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
3581 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
3582 luxFloat("red X", cspaceredX, 0.0, 1.0, "red X", "Red component X weight", gui, 1.0)
3583 luxFloat("red Y", cspaceredY, 0.0, 1.0, "red Y", "Red component Y weight", gui, 1.0)
3584 luxFloat("green X", cspacegreenX, 0.0, 1.0, "green X", "Green component X weight", gui, 1.0)
3585 luxFloat("green Y", cspacegreenY, 0.0, 1.0, "green Y", "Green component Y weight", gui, 1.0)
3586 luxFloat("blue X", cspaceblueX, 0.0, 1.0, "blue X", "Blue component X weight", gui, 1.0)
3587 luxFloat("blue Y", cspaceblueY, 0.0, 1.0, "blue Y", "Blue component Y weight", gui, 1.0)
3588 if gui: gui.newline(" Gamma:")
3589 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
3591 str += "\n \"float colorspace_white\" [%f %f]"%(cspacewhiteX.get(), cspacewhiteY.get())
3592 str += "\n \"float colorspace_red\" [%f %f]"%(cspaceredX.get(), cspaceredY.get())
3593 str += "\n \"float colorspace_green\" [%f %f]"%(cspacegreenX.get(), cspacegreenY.get())
3594 str += "\n \"float colorspace_blue\" [%f %f]"%(cspaceblueX.get(), cspaceblueY.get())
3595 str += "\n \"float gamma\" [%f]"%(gamma.get())
3600 def luxPixelFilter(scn, gui=None):
3601 global icon_c_filter
3604 filtertype = luxProp(scn, "pixelfilter.type", "mitchell")
3605 str = luxIdentifier("PixelFilter", filtertype, ["box", "gaussian", "mitchell", "sinc", "triangle"], "FILTER", "select pixel filter type", gui, icon_c_filter)
3608 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3609 showadvanced = luxProp(scn, "pixelfilter.showadvanced", parammodeadvanced.get())
3610 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
3612 showhelp = luxProp(scn, "pixelfilter.showhelp", "false")
3613 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
3615 if filtertype.get() == "box":
3616 if showadvanced.get()=="true":
3617 # Advanced parameters
3618 if gui: gui.newline()
3619 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)
3620 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)
3621 if filtertype.get() == "gaussian":
3622 if showadvanced.get()=="true":
3623 # Advanced parameters
3624 if gui: gui.newline()
3625 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)
3626 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)
3627 if gui: gui.newline()
3628 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)
3629 if filtertype.get() == "mitchell":
3630 if showadvanced.get()=="false":
3631 # Default parameters
3632 if gui: gui.newline("", 8, 0, None, [0.4,0.4,0.4])
3633 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.3333)
3634 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 2.0, 1)
3635 sharp = slidval.getFloat()
3637 str += "\n \"float xwidth\" [%f]" % (width)
3638 str += "\n \"float ywidth\" [%f]" % (width)
3639 str += "\n \"float B\" [%f]" % (sharp)
3640 str += "\n \"float C\" [%f]" % (sharp)
3641 str += "\n \"bool supersample\" [\"true\"]"
3643 if showadvanced.get()=="true":
3644 # Advanced parameters
3645 if gui: gui.newline()
3646 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.mitchell.xwidth", 1.5), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
3647 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.mitchell.ywidth", 1.5), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
3648 if gui: gui.newline()
3650 optmode = luxProp(scn, "pixelfilter.mitchell.optmode", "slider")
3651 luxOption("optmode", optmode, ["slider", "preset", "manual"], "Mode", "Mode of configuration", gui, 0.5)
3653 if(optmode.get() == "slider"):
3654 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.3333)
3655 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 1.5, 1)
3656 # rule: B + 2*c = 1.0
3657 # we must apply the rule only when supersampling is disabled
3658 if luxProp(scn, 'pixelfilter.mitchell.supersample', 'true').get() != 'true':
3659 C = slidval.getFloat() * 0.5
3660 B = 1.0 - slidval.getFloat()
3662 B = C = slidval.getFloat()
3663 str += "\n \"float B\" [%f]"%(B)
3664 str += "\n \"float C\" [%f]"%(C)
3665 elif(optmode.get() == "preset"):
3666 print("not implemented")
3668 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)
3669 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)
3670 str += luxBool("supersample", luxProp(scn, "pixelfilter.mitchell.supersample", "true"), "Supersample", "Use supersampling to avoid aliasing with sharp narrow filter", gui, 1.0)
3672 if filtertype.get() == "sinc":
3673 if showadvanced.get()=="true":
3674 # Advanced parameters
3675 if gui: gui.newline()
3676 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)
3677 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)
3678 if gui: gui.newline()
3679 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)
3680 if filtertype.get() == "triangle":
3681 if showadvanced.get()=="true":
3682 # Advanced parameters
3683 if gui: gui.newline()
3684 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)
3685 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)
3688 def luxSampler(scn, gui=None):
3689 global icon_c_sampler, icon_help
3692 samplertype = luxProp(scn, "sampler.type", "metropolis")
3693 str = luxIdentifier("Sampler", samplertype, ["metropolis", "erpt", "lowdiscrepancy", "random"], "SAMPLER", "select sampler type", gui, icon_c_sampler)
3696 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3697 showadvanced = luxProp(scn, "sampler.showadvanced", parammodeadvanced.get())
3698 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
3700 showhelp = luxProp(scn, "sampler.showhelp", "false")
3701 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
3703 if samplertype.get() == "metropolis":
3704 if showadvanced.get()=="false":
3705 # Default parameters
3706 if gui: gui.newline(" Mutation:", 8, 0, None, [0.4,0.4,0.4])
3707 strength = luxProp(scn, "sampler.metro.strength", 0.6)
3708 luxFloat("strength", strength, 0.0, 1.0, "strength", "Mutation Strength (lmprob = 1.0-strength)", gui, 2.0, 1)
3709 v = 1.0 - strength.get()
3710 str += "\n \"float largemutationprob\" [%f]"%v
3711 if showadvanced.get()=="true":
3712 # Advanced parameters
3713 if gui: gui.newline(" Mutation:")
3714 str += luxFloat("largemutationprob", luxProp(scn, "sampler.metro.lmprob", 0.4), 0.0, 1.0, "LM.prob.", "Probability of generating a large sample (mutation)", gui)
3715 str += luxInt("maxconsecrejects", luxProp(scn, "sampler.metro.maxrejects", 512), 0, 32768, "max.rejects", "number of consecutive rejects before a new mutation is forced", gui)
3716 if gui: gui.newline(" Screen:")
3717 #str += luxInt("initsamples", luxProp(scn, "sampler.metro.initsamples", 262144), 1, 1000000, "initsamples", "", gui)
3718 str += luxBool("usevariance",luxProp(scn, "sampler.metro.usevariance", "false"), "usevariance", "Accept based on variance", gui, 1.0)
3720 if showhelp.get()=="true":
3721 if gui: gui.newline(" Description:", 8, 0, icon_help, [0.4,0.5,0.56])
3722 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
3723 Draw.Text("A Metropolis-Hastings mutating sampler which implements MLT", 'small')
3725 if samplertype.get() == "erpt":
3726 #str += luxInt("initsamples", luxProp(scn, "sampler.erpt.initsamples", 100000), 1, 1000000, "initsamples", "", gui)
3727 if gui: gui.newline(" Mutation:")
3728 str += luxInt("chainlength", luxProp(scn, "sampler.erpt.chainlength", 512), 1, 32768, "chainlength", "The number of mutations from a given seed", gui)
3729 if gui: gui.newline()
3730 str += luxInt("stratawidth", luxProp(scn, "sampler.erpt.stratawidth", 256), 1, 32768, "stratawidth", "The number of x/y strata for stratified sampling of seeds", gui)
3732 if samplertype.get() == "lowdiscrepancy":
3733 if gui: gui.newline(" PixelSampler:")
3734 str += luxOption("pixelsampler", luxProp(scn, "sampler.lowdisc.pixelsampler", "lowdiscrepancy"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
3735 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)
3737 if samplertype.get() == "random":
3738 if gui: gui.newline(" PixelSampler:")
3739 str += luxOption("pixelsampler", luxProp(scn, "sampler.random.pixelsampler", "vegas"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
3740 if gui: gui.newline()
3741 str += luxInt("pixelsamples", luxProp(scn, "sampler.random.pixelsamples", 4), 1, 512, "pixelsamples", "Allows you to specify how many samples per pixel are computed", gui)
3744 def luxSurfaceIntegrator(scn, gui=None):
3745 global icon_c_integrator
3748 integratortype = luxProp(scn, "sintegrator.type", "bidirectional")
3750 str = luxIdentifier("SurfaceIntegrator", integratortype, ["directlighting", "path", "bidirectional", "exphotonmap", "distributedpath", "igi" ], "INTEGRATOR", "select surface integrator type", gui, icon_c_integrator)
3753 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3754 showadvanced = luxProp(scn, "sintegrator.showadvanced", parammodeadvanced.get())
3755 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
3757 showhelp = luxProp(scn, "sintegrator.showhelp", "false")
3758 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
3760 if integratortype.get() == "directlighting":
3761 if showadvanced.get()=="false":
3762 # Default parameters
3763 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3764 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 2.0)
3766 if showadvanced.get()=="true":
3767 # Advanced parameters
3768 if gui: gui.newline(" Depth:")
3769 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "max-depth", "The maximum recursion depth for ray casting", gui)
3770 str += luxOption("lightstrategy", luxProp(scn, "sintegrator.dlighting.lightstrategy", "auto"), ["one", "all", "auto", "importance", "powerimp", "allpowerimp", "logpowerimp"], "light strategy", "select directlighting strategy", gui)
3771 str += luxInt("shadowraycount", luxProp(scn, "sintegrator.dlighting.shadowraycount", 1), 1, 512, "shadow ray count", "Number of shadow rays traced per sample", gui, 2.0)
3773 if integratortype.get() == "path":
3774 if showadvanced.get()=="false":
3775 # Default parameters
3776 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3777 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 1.0)
3778 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
3779 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
3781 if showadvanced.get()=="true":
3782 # Advanced parameters
3783 if gui: gui.newline(" Depth:")
3784 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "maxdepth", "The maximum recursion depth for ray casting", gui)
3785 str += luxOption("lightstrategy", luxProp(scn, "sintegrator.path.lightstrategy", "auto"), ["one", "all", "auto", "importance", "powerimp", "allpowerimp", "logpowerimp"], "light strategy", "select directlighting strategy", gui)
3786 if gui: gui.newline(" RR:")
3787 rrstrat = luxProp(scn, "sintegrator.path.rrstrategy", "efficiency")
3788 str += luxOption("rrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette path termination strategy", gui)
3789 if rrstrat.get() == "probability":
3790 str += luxFloat("rrcontinueprob", luxProp(scn, "sintegrator.path.rrcontinueprob", 0.65), 0.0, 1.0, "rrprob", "Russian roulette continue probability", gui)
3791 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
3792 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
3793 str += luxInt("shadowraycount", luxProp(scn, "sintegrator.dlighting.shadowraycount", 1), 1, 512, "shadow ray count", "Number of shadow rays traced per sample", gui, 2.0)
3795 if integratortype.get() == "bidirectional":
3796 if showadvanced.get()=="false":
3797 # Default parameters
3798 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3799 bounces = luxProp(scn, "sintegrator.bidir.bounces", 16)
3800 luxInt("bounces", bounces, 5, 32, "bounces", "The maximum recursion depth for ray casting (in both directions)", gui, 2.0)
3801 str += "\n \"integer eyedepth\" [%i]\n"%bounces.get()
3802 str += " \"integer lightdepth\" [%i]"%bounces.get()
3804 if showadvanced.get()=="true":
3805 # Advanced parameters
3806 if gui: gui.newline(" Depth:")
3807 str += luxInt("eyedepth", luxProp(scn, "sintegrator.bidir.eyedepth", 16), 0, 2048, "eyedepth", "The maximum recursion depth for ray casting", gui)
3808 str += luxInt("lightdepth", luxProp(scn, "sintegrator.bidir.lightdepth", 16), 0, 2048, "lightdepth", "The maximum recursion depth for light ray casting", gui)
3809 str += luxOption("strategy", luxProp(scn, "sintegrator.bidir.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3811 str += luxFloat('eyerrthreshold', luxProp(scn, "sintegrator.bidir.eyerrthreshold", 0), 0, 1, "eyerrthreshold", "The minimum probability for russian roulette eye subpath termination ", gui)
3812 str += luxFloat('lightrrthreshold', luxProp(scn, "sintegrator.bidir.lightrrthreshold", 0), 0, 1, "lightrrthreshold", "The minimum probability for russian roulette light subpath termination ", gui)
3814 if integratortype.get() == "exphotonmap":
3815 if gui: gui.newline(" Render:")
3816 str += luxOption("renderingmode", luxProp(scn, "sintegrator.photonmap.renderingmode", "directlighting"), ["directlighting", "path"], "renderingmode", "select rendering mode", gui)
3817 str += luxOption("lightstrategy", luxProp(scn, "sintegrator.photonmap.lightstrategy", "auto"), ["one", "all", "auto", "importance", "powerimp", "allpowerimp", "logpowerimp"], "light strategy", "select directlighting strategy", gui)
3818 str += luxInt("shadowraycount", luxProp(scn, "sintegrator.dlighting.shadowraycount", 1), 1, 512, "shadow ray count", "Number of shadow rays traced per sample", gui, 2.0)
3819 str += luxInt("maxphotondepth", luxProp(scn, "sintegrator.photonmap.maxphotondepth", 10), 1, 1024, "maxphotondepth", "The maximum recursion depth of photon tracing", gui)
3820 str += luxInt("maxdepth", luxProp(scn, "sintegrator.photonmap.maxdepth", 6), 1, 1024, "maxdepth", "The maximum recursion depth of specular reflection and refraction", gui)
3821 str += luxFloat("maxphotondist", luxProp(scn, "sintegrator.photonmap.maxphotondist", 0.1), 0.0, 10.0, "maxphotondist", "The maximum distance between a point being shaded and a photon that can contribute to that point", gui)
3822 str += luxInt("nphotonsused", luxProp(scn, "sintegrator.photonmap.nphotonsused", 50), 0, 1000000, "nphotonsused", "The number of photons to use in density estimation", gui)
3824 if gui: gui.newline(" Photons:")
3825 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)
3826 str += luxInt("directphotons", luxProp(scn, "sintegrator.photonmap.dphotons", 1000000), 0, 10000000, "direct", "The number of photons to shoot for direct lighting during preprocessing of the photon map", gui)
3827 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)
3828 if gui: gui.newline(" FinalGather:")
3829 fg = luxProp(scn, "sintegrator.photonmap.fgather", "true")
3830 str += luxBool("finalgather", fg, "finalgather", "Enable use of final gather during rendering", gui)
3831 if fg.get() == "true":
3832 rrstrat = luxProp(scn, "sintegrator.photonmap.rrstrategy", "efficiency")
3833 str += luxOption("rrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette gather termination strategy", gui)
3834 str += luxInt("finalgathersamples", luxProp(scn, "sintegrator.photonmap.fgathers", 32), 1, 1024, "samples", "The number of finalgather samples to take per pixel during rendering", gui)
3835 str += luxFloat("gatherangle", luxProp(scn, "sintegrator.photonmap.gangle", 10.0), 0.0, 360.0, "gatherangle", "Angle for final gather", gui)
3836 if rrstrat.get() == "probability":
3837 str += luxFloat("rrcontinueprob", luxProp(scn, "sintegrator.photonmap.rrcontinueprob", 0.65), 0.0, 1.0, "rrcontinueprob", "Probability for russian roulette particle tracing termination", gui)
3839 if showadvanced.get()=="true":
3840 if gui: gui.newline(" Debug options:")
3841 dbg_enabledirect = luxProp(scn, "sintegrator.photonmap.dbg_enabledirect", "false")
3842 dbg_enableradiancemap = luxProp(scn, "sintegrator.photonmap.dbg_enableradiancemap", "false")
3843 dbg_enableindircaustic = luxProp(scn, "sintegrator.photonmap.dbg_enableindircaustic", "false")
3844 dbg_enableindirdiffuse = luxProp(scn, "sintegrator.photonmap.dbg_enableindirdiffuse", "false")
3845 dbg_enableindirspecular = luxProp(scn, "sintegrator.photonmap.dbg_enableindirspecular", "false")
3846 str += luxBool("dbg_enabledirect", dbg_enabledirect, "Direct lighing", "Enable visual inspection of direct ligting", gui)
3847 str += luxBool("dbg_enableradiancemap", dbg_enableradiancemap, "Radiancemap", "Enable visual inspection of radiance map", gui)
3848 str += luxBool("dbg_enableindircaustic", dbg_enableindircaustic, "Indirect caustics", "Enable visual inspection of indirect caustic map", gui)
3849 str += luxBool("dbg_enableindirdiffuse", dbg_enableindirdiffuse, "Indirect diffuse", "Enable visual inspection of indirect diffuse map", gui)
3850 str += luxBool("dbg_enableindirspecular", dbg_enableindirspecular, "Indirect specular", "Enable visual inspection of indirect specular map", gui)
3852 if integratortype.get() == "distributedpath":
3853 str += luxOption("strategy", luxProp(scn, "sintegrator.distributedpath.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3854 if gui: gui.newline(" Direct:")
3855 str += luxBool("directsampleall",luxProp(scn, "sintegrator.distributedpath.directsampleall", "true"), "Direct ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3856 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)
3857 str += luxBool("indirectsampleall",luxProp(scn, "sintegrator.distributedpath.indirectsampleall", "false"), "Indirect ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3858 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)
3859 if gui: gui.newline(" Diffuse:")
3860 str += luxInt("diffusereflectdepth", luxProp(scn, "sintegrator.distributedpath.diffusereflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for diffuse reflection ray casting", gui, 0.5)
3861 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)
3862 str += luxInt("diffuserefractdepth", luxProp(scn, "sintegrator.distributedpath.diffuserefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for diffuse refraction ray casting", gui, 0.5)
3863 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)
3864 str += luxBool("directdiffuse",luxProp(scn, "sintegrator.distributedpath.directdiffuse", "true"), "DL", "Include diffuse direct light sample at first vertex", gui, 0.20)
3865 str += luxBool("indirectdiffuse",luxProp(scn, "sintegrator.distributedpath.indirectdiffuse", "true"), "IDL", "Include diffuse indirect light sample at first vertex", gui, 0.20)
3866 if gui: gui.newline(" Glossy:")
3867 str += luxInt("glossyreflectdepth", luxProp(scn, "sintegrator.distributedpath.glossyreflectdepth", 2), 0, 2048, "Reflect", "The maximum recursion depth for glossy reflection ray casting", gui, 0.50)
3868 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)
3869 str += luxInt("glossyrefractdepth", luxProp(scn, "sintegrator.distributedpath.glossyrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for glossy refraction ray casting", gui, 0.50)
3870 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)
3871 str += luxBool("directglossy",luxProp(scn, "sintegrator.distributedpath.directglossy", "true"), "DL", "Include glossy direct light sample at first vertex", gui, 0.20)
3872 str += luxBool("indirectglossy",luxProp(scn, "sintegrator.distributedpath.indirectglossy", "true"), "IDL", "Include glossy indirect light sample at first vertex", gui, 0.20)
3873 if gui: gui.newline(" Specular:")
3874 str += luxInt("specularreflectdepth", luxProp(scn, "sintegrator.distributedpath.specularreflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for specular reflection ray casting", gui, 1.0)
3875 str += luxInt("specularrefractdepth", luxProp(scn, "sintegrator.distributedpath.specularrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for specular refraction ray casting", gui, 1.0)
3876 #if gui: gui.newline(" Caustics:")
3877 #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)
3878 #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)
3880 usereject = luxProp(scn, "sintegrator.distributedpath.usereject", "false")
3881 luxCollapse("usereject", usereject, "Rejection", "Enable Rejection system to eliminate bright contributions", gui, 2.0)
3883 if usereject.get()=="true":
3884 if gui: gui.newline(" Diffuse:")
3886 diffusereflectreject = luxProp(scn, "sintegrator.distributedpath.difreflreject", "false")
3887 str += luxBool("diffusereflectreject", diffusereflectreject, "Reflect", "Enable Rejection for Diffuse Reflection", gui, 0.4)
3888 if diffusereflectreject.get()=="true":
3889 str += luxFloat("diffusereflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.difreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3891 diffuserefractreject = luxProp(scn, "sintegrator.distributedpath.difrefrreject", "false")
3892 str += luxBool("diffuserefractreject", diffuserefractreject, "Refract", "Enable Rejection for Diffuse Refraction", gui, 0.4)
3893 if diffuserefractreject.get()=="true":
3894 str += luxFloat("diffuserefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.difrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3896 if gui: gui.newline(" Glossy:")
3898 glossyreflectreject = luxProp(scn, "sintegrator.distributedpath.glosreflreject", "false")
3899 str += luxBool("glossyreflectreject", glossyreflectreject, "Reflect", "Enable Rejection for Glossy Reflection", gui, 0.4)
3900 if glossyreflectreject.get()=="true":
3901 str += luxFloat("glossyreflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3903 glossyrefractreject = luxProp(scn, "sintegrator.distributedpath.glosrefrreject", "false")
3904 str += luxBool("glossyrefractreject", glossyrefractreject, "Refract", "Enable Rejection for Glossy Refraction", gui, 0.4)
3905 if glossyrefractreject.get()=="true":
3906 str += luxFloat("glossyrefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3908 if integratortype.get() == "igi":
3909 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3910 depth = luxProp(scn, "sintegrator.igi.maxdepth", 5)
3911 luxInt("maxdepth", depth, 1, 32, "maxdepth", "The maximum recursion depth for ray casting", gui, 2.0)
3912 if showadvanced.get()=="true":
3913 # Advanced parameters
3914 if gui: gui.newline(" VLights:")
3915 str += luxInt("nsets", luxProp(scn, "sintegrator.igi.nsets", 4), 1, 100, "nsets", "The number of virtual lights sets", gui)
3916 str += luxInt("nlights", luxProp(scn, "sintegrator.igi.nlights", 64), 1, 1000, "nlights", "The number of light paths per light set", gui)
3917 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)
3922 def luxVolumeIntegrator(scn, gui=None):
3923 global icon_c_volumeintegrator
3926 integratortype = luxProp(scn, "vintegrator.type", "single")
3927 str = luxIdentifier("VolumeIntegrator", integratortype, ["emission", "single"], "VOLUME INT", "select volume integrator type", gui, icon_c_volumeintegrator)
3928 if integratortype.get() == "emission":
3929 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3930 if integratortype.get() == "single":
3931 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3934 def luxEnvironment(scn, gui=None):
3935 global icon_c_environment
3938 def componentRotation(key, hint, scn, gui, complimentary=False):
3940 rotZ = luxProp(scn, key+".rotation", 0.0)
3941 rotY = luxProp(scn, key+".rotationY", 0.0)
3942 rotX = luxProp(scn, key+".rotationX", 0.0)
3943 luxFloat(key+".rotationX", rotX, 0.0, 360.0, "rot X", hint+" rotation X", gui, 0.66)
3944 luxFloat(key+".rotationY", rotY, 0.0, 360.0, "rot Y", hint+" rotation Y", gui, 0.66)
3945 luxFloat(key+".rotationZ", rotZ, 0.0, 360.0, "rot Z", hint+" rotation Z", gui, 0.66)
3946 if rotZ.get() != 0 or rotY.get() != 0 or rotX.get() != 0:
3948 str += "\nAttributeEnd\nAttributeBegin\n"
3949 str += "\tRotate %d 1 0 0\n"%(rotX.get())
3950 str += "\tRotate %d 0 1 0\n"%(rotY.get())
3951 str += "\tRotate %d 0 0 1\n"%(rotZ.get())
3952 if gui: gui.newline()
3954 envtype = luxProp(scn, "env.type", "infinite")
3955 lsstr = luxIdentifier("LightSource", envtype, ["none", "infinite", "sunsky"], "ENVIRONMENT", "select environment light type", gui, icon_c_environment)
3956 if gui: gui.newline()
3963 if envtype.get() != "none":
3965 if envtype.get() in ("infinite", "infinitesample"):
3966 str += componentRotation('env', 'environment map', scn, gui)
3967 env_lg = luxProp(scn, "env.lightgroup", "default")
3968 luxString("env.lightgroup", env_lg, "lightgroup", "Environment light group", gui)
3969 if luxProp(scn, "nolg", "false").get()!="true":
3970 lsstr = '\nLightGroup "' + env_lg.get() + '"' + lsstr
3972 str += luxFloat("gain", luxProp(scn, "env.infinite.gain", 1.0), 0.0001, 10000.0, "gain", "Infinite Env Gain", gui, 1.0)
3973 mapping = luxProp(scn, "env.infinite.mapping", "latlong")
3974 mappings = ["latlong","angular","vcross"]
3975 mapstr = luxOption("mapping", mapping, mappings, "mapping", "Select mapping type", gui, 1.0)
3976 mapstr += luxFloat("gamma", luxProp(scn, "env.infinite.gamma", 1.0), 0.0, 6.0, "gamma", "", gui, 1.0)
3977 map = luxProp(scn, "env.infinite.mapname", "")
3978 mapstr += luxFile("mapname", map, "map-file", "filename of the environment map", gui, 2.0)
3984 worldcolor = Blender.World.Get('World').getHor()
3985 str += "\n \"color L\" [%g %g %g]" %(worldcolor[0], worldcolor[1], worldcolor[2])
3988 if envtype.get() == "sunsky":
3989 str += componentRotation('sunsky', 'sunsky', scn, gui)
3990 skycomponentProp = luxProp(scn, "env.sunsky.skycomponent", "true")
3991 luxCollapse("skycomponent", skycomponentProp, "Sky Component", "Add Skydome Light Component", gui, 2.0)
3992 if skycomponentProp.get() == "true":
3993 sun_lg = luxProp(scn, "env.sky_lightgroup", "default")
3994 luxString("env.lightgroup", sun_lg, "lightgroup", "Sky component light group", gui)
3995 if luxProp(scn, "nolg", "false").get() != "true":
3996 skystr += '\nLightGroup "' + sun_lg.get() + '"'
3997 skystr += "\nLightSource \"sky\" "
3998 skystr += luxFloat("gain", luxProp(scn, "env.sunsky.sky_gain", 1.0), 0.0001, 100.0, "gain", "Sun light gain", gui)
3999 sunhaloProp = luxProp(scn, "env.sunsky.halo", "true")
4000 luxBool("sunhalo", sunhaloProp, "Sun Halo", "Atmospheric halo around sun disk", gui)
4001 skystr += luxFloat("turbidity", luxProp(scn, "env.sunsky.sky_turbidity", 2.2), 2.0, 50.0, "turbidity", "Atmospheric turbidity", gui)
4002 if sunhaloProp.get() == "true":
4005 suncomponentProp = luxProp(scn, "env.sunsky.suncomponent", envtype.get() == "sunsky" and "true" or "false")
4006 luxCollapse("suncomponent", suncomponentProp, "Sun Component", "Add Sunlight Component", gui, 2.0)
4007 if suncomponentProp.get() == "true":
4008 sun_lg = luxProp(scn, "env.sun_lightgroup", "default")
4009 luxString("env.lightgroup", sun_lg, "lightgroup", "Sun component light group", gui)
4010 if luxProp(scn, "nolg", "false").get() != "true":
4011 sunstr += '\nLightGroup "' + sun_lg.get() + '"'
4012 sunstr += "\nLightSource \"sun\" "
4015 if envtype.get() in ("infinite", "infinitesample"):
4016 infinitesunProp = luxProp(scn, "env.infinite.suncomponent", "false")
4017 luxCollapse("infinitesun", infinitesunProp, "Sun Component", "Add Sunlight Component", gui, 2.0)
4018 if infinitesunProp.get() == "true":
4019 str += componentRotation('envsun', 'sun component', scn, gui, True)
4020 sun_lg = luxProp(scn, "env.sun_lightgroup", "default")
4021 luxString("env.lightgroup", sun_lg, "lightgroup", "Sun component light group", gui)
4022 if luxProp(scn, "nolg", "false").get() != "true":
4023 sunstr += '\nLightGroup "' + sun_lg.get() + '"'
4024 sunstr += "\nLightSource \"sun\" "
4027 if suncomponent == 1:
4029 for obj in scn.objects:
4030 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
4031 if obj.getData(mesh=1).getType() == 1: # sun object # data
4034 sunstr += luxFloat("gain", luxProp(scn, "env.sunsky.sun_gain", 1.0), 0.0001, 100.0, "gain", "Sun light gain", gui)
4036 invmatrix = Mathutils.Matrix(sun.getInverseMatrix())
4037 sunstr += "\n \"vector sundir\" [%f %f %f]" %(invmatrix[0][2], invmatrix[1][2], invmatrix[2][2])
4038 sunstr += luxFloat("relsize", luxProp(scn, "env.sunsky.sun_relsize", 1.0), 0.0, 100.0, "rel.size", "Relative sun disk size", gui)
4039 sunstr += luxFloat("turbidity", luxProp(scn, "env.sunsky.sun_turbidity", 2.2), 2.0, 50.0, "turbidity", "Atmospheric turbidity", gui)
4041 if sunhalo == 1 and skystr != "":
4042 skystr += "\n \"vector sundir\" [%f %f %f]" %(invmatrix[0][2], invmatrix[1][2], invmatrix[2][2])
4044 showGeo = luxProp(sun, 'sc.show', 'false')
4045 if gui: luxCollapse("sc.show", showGeo, "Geographic Sun", "Set sun position by world location, date and time", gui, 2.0)
4046 if showGeo.get() == 'true':
4047 if gui: gui.newline("Geographic:")
4048 sc = sun_calculator(sun)
4050 luxInt("sc.day", luxProp(sun, "sc.day", 1), 1, 31, "day", "Local date: day", gui, 0.66)
4051 luxInt("sc.month", luxProp(sun, "sc.month", 1), 1, 12, "month", "Local date: month", gui, 0.67)
4052 luxInt("sc.year", luxProp(sun, "sc.year", 2009), 1, 2500, "year", "Local date: year", gui, 0.66)
4054 sc_hour = luxProp(sun, "sc.hour", 0)
4055 sc_minute = luxProp(sun, "sc.minute", 0)
4056 sc_dayminutes = luxProp(sun, 'sc.dayminutes', 0.0)
4057 sunIpo = luxProp(sun, 'sc.ipo', 'false')
4058 if luxProp(scn, 'useparamkeys', 'false').get() == 'true':
4059 if gui: luxCollapse('sc.ipo', sunIpo, 'Sun IPO Keyframing', 'Set sun position using IPO keyframes', gui, 2.0)
4060 if sunIpo.get() == 'true':
4061 luxFloat('sc.dayminutes', sc_dayminutes, 0.0, 1439.0, 'IPO day minutes', 'Day minutes for IPO keyframing', gui, 2.0)
4062 if int(sc_dayminutes.get()) != sc_hour.get()*60 + sc_minute.get():
4063 sc_hour.set(int(sc_dayminutes.get()/60))
4064 sc_minute.set(int(sc_dayminutes.get()%60))
4066 luxInt("sc.hour", sc_hour, 0, 23, "hour", "Local time: hour", gui, 0.72)
4067 luxInt("sc.minute", sc_minute, 0, 59, "minute", "Local time: minute", gui, 0.72)
4068 luxBool("sc.dst", luxProp(sun, "sc.dst", 'false'), "DST", "DST", gui, 0.28)
4070 r = gui.getRect(0.28,1)
4071 Draw.Button("NOW", 0, r[0], r[1], r[2], r[3], "Set to current time", lambda e,v: sc.now())
4073 r = gui.getRect(0.3,1)
4074 Draw.Button("Preset", 0, r[0], r[1], r[2], r[3], "Choose a preset location", lambda e,v: sc.set_location(
4075 Draw.PupTreeMenu(sun_calculator.location_list)
4078 luxFloat("sc.lat", luxProp(sun, "sc.lat", 0.0), -90.0, 90.0, "lat", "Location: latitude. Positive value for north hemisphere, negative value for south hemisphere", gui, 0.56)
4079 luxFloat("sc.long", luxProp(sun, "sc.long", 0.0), -180.0, 180.0, "long", "Location: longitude. Positive value for west hemisphere, negative value for east hemisphere", gui, 0.56)
4080 luxInt("sc.tz", luxProp(sun, "sc.tz", 0), -12, 12, "timezone", "Local time: timezone offset from GMT", gui, 0.56)
4083 r = gui.getRect(2,1)
4084 Draw.Button("Calculate", 0, r[0], r[1], r[2], r[3], "Calculate sun's position", lambda e,v: sc.compute())
4088 gui.newline(); r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
4089 Draw.Text("create a Blender Sun Lamp")
4091 if skystr != "": str += skystr
4092 if sunstr != "": str += sunstr
4095 #if gui: gui.newline("GLOBAL:", 8, 0, None, [0.75,0.5,0.25])
4096 #luxFloat("scale", luxProp(scn, "global.scale", 1.0), 0.0, 10.0, "scale", "global world scale", gui)
4097 if gui: gui.newline("WORLD MEDIUM:", 8, 0, None, [0.75,0.5,0.25])
4098 luxNamedVolumeTexture(0, gui)
4102 class sun_calculator:
4103 #Based on SunLight v1.0 by Miguel Kabantsov (miguelkab@gmail.com)
4104 #Replaces the faulty sun position calculation algorythm with a precise calculation (Source for algorythm: http://de.wikipedia.org/wiki/Sonnenstand),
4105 #Co-Ordinates: http://www.bcca.org/misc/qiblih/latlong.html
4106 #Author: Nils-Peter Fischer (Nils-Peter.Fischer@web.de)
4124 ("Antwerp, Belgium", 67),
4125 ("Berlin, Germany", 1),
4126 ("Bratislava, Slovak Republic", 70),
4127 ("Brno, Czech Republic", 72),
4128 ("Brussles, Belgium", 68),
4129 ("Geneva, Switzerland", 65),
4130 ("Helsinki, Finland", 7),
4131 ("Innsbruck, Austria", 62),
4132 ("Kyiv, Ukraine", 64),
4133 ("London, England", 10),
4134 ("Lyon, France", 66),
4135 ("Nitra, Slovak Republic", 69),
4136 ("Oslo, Norway", 58),
4137 ("Paris, France", 15),
4138 ("Praha, Czech Republic", 71),
4139 ("Rome, Italy", 18),
4140 ("Telfs, Austria", 63),
4141 ("Warsaw, Poland", 74),
4142 ("Wroclaw, Poland", 73),
4143 ("Zurich, Switzerland", 21),
4147 ("Beijing, China", 0),
4148 ("Bombay, India", 2),
4149 ("Buenos Aires, Argentina", 3),
4150 ("Cairo, Egypt", 4),
4151 ("Cape Town, South Africa", 5),
4152 ("Caracas, Venezuela", 6),
4153 ("Curitiba, Brazil", 60),
4154 ("Hong Kong, China", 8),
4155 ("Jerusalem, Israel", 9),
4156 ("Joinville, Brazil", 61),
4157 ("Mexico City, Mexico", 11),
4158 ("Moscow, Russia", 12),
4159 ("New Delhi, India", 13),
4160 ("Ottawa, Canada", 14),
4161 ("Rio de Janeiro, Brazil", 16),
4162 ("Riyadh, Saudi Arabia", 17),
4163 ("Sao Paulo, Brazil", 59),
4164 ("Sydney, Australia", 19),
4165 ("Tokyo, Japan", 20),
4169 ("Albuquerque, NM", 22),
4170 ("Anchorage, AK", 23),
4171 ("Atlanta, GA", 24),
4173 ("Birmingham, AL", 26),
4174 ("Bismarck, ND", 27),
4176 ("Boulder, CO", 29),
4177 ("Chicago, IL", 30),
4180 ("Detroit, MI", 33),
4181 ("Honolulu, HI", 34),
4182 ("Houston, TX", 35),
4183 ("Indianapolis, IN", 36),
4184 ("Jackson, MS", 37),
4185 ("Kansas City, MO", 38),
4186 ("Los Angeles, CA", 39),
4187 ("Menomonee Falls, WI", 40),
4189 ("Minneapolis, MN", 42),
4190 ("New Orleans, LA", 43),
4191 ("New York City, NY", 44),
4192 ("Oklahoma City, OK", 45),
4193 ("Philadelphia, PA", 46),
4194 ("Phoenix, AZ", 47),
4195 ("Pittsburgh, PA", 48),
4196 ("Portland, ME", 49),
4197 ("Portland, OR", 50),
4198 ("Raleigh, NC", 51),
4199 ("Richmond, VA", 52),
4200 ("Saint Louis, MO", 53),
4201 ("San Diego, CA", 54),
4202 ("San Francisco, CA", 55),
4203 ("Seattle, WA", 56),
4204 ("Washington DC", 57),
4210 67: ( 51.2167, -4.4, 1),
4211 1: ( 52.33, -13.30, 1),
4212 70: ( 48.17, -17.17, 1),
4213 72: ( 49.2, -16.63, 1),
4214 68: ( 58.8467, -4.3525, 1),
4215 65: ( 46.217, -6.150, 1),
4216 7: ( 60.1667, -24.9667,2),
4217 62: ( 47.2672, -11.3928, 1),
4218 64: ( 50.75, -30.0833, 2),
4219 10: ( 51.50, 0.0, 0),
4220 66: ( 45.767, -4.833, 1),
4221 69: ( 48.32, -18.07, 1),
4222 58: ( 59.56, -10.41, 1),
4223 15: ( 48.8667, -2.667, 1),
4224 71: ( 50.08, -14.46, 1),
4225 18: ( 41.90, -12.4833, 1),
4226 63: ( 47.3, -11.0667, 1),
4227 74: ( 52.232, -21.008, 1),
4228 73: ( 51.108, -17.038, 1),
4229 21: ( 47.3833, -8.5333, 1),
4232 0: ( 39.9167, -116.4167, 8),
4233 2: ( 18.9333, -72.8333, 5.5),
4234 3: (-34.60, 58.45, -3),
4235 4: ( 30.10, -31.3667, 2),
4236 5: (-33.9167, -18.3667, 2),
4237 6: ( 10.50, 66.9333, -4),
4238 60: (-25.4278, 49.2731, -3),
4239 8: ( 22.25, -114.1667, 8),
4240 9: ( 31.7833, -35.2333, 2),
4241 61: (-29.3044, 48.8456, -3),
4242 11: ( 19.4, 99.15, -6),
4243 12: ( 55.75, -37.5833, 3),
4244 13: ( 28.6, -77.2, 5.5),
4245 14: ( 45.41667, 75.7, -5),
4246 16: (-22.90, 43.2333, -3),
4247 17: ( 24.633, -46.71667, 3),
4248 59: ( -23.5475, 46.6361, -3),
4249 19: (-33.8667, -151.2167,10),
4250 20: ( 35.70, -139.7667, 9),
4253 22: ( 35.0833, 106.65, -7),
4254 23: ( 61.217, 149.90, -9),
4255 24: ( 33.733, 84.383, -5),
4256 25: ( 30.283, 97.733, -6),
4257 26: ( 33.521, 86.8025, -6),
4258 27: ( 46.817, 100.783, -6),
4259 28: ( 42.35, 71.05, -5),
4260 29: ( 40.125, 105.237, -7),
4261 30: ( 41.85, 87.65, -6),
4262 31: ( 32.46, 96.47, -6),
4263 32: ( 39.733, 104.983, -7),
4264 33: ( 42.333, 83.05, -5),
4265 34: ( 21.30, 157.85, -10),
4266 35: ( 29.75, 95.35, -6),
4267 36: ( 39.767, 86.15, -5),
4268 37: ( 32.283, 90.183, -6),
4269 38: ( 39.083, 94.567, -6),
4270 39: ( 34.05, 118.233, -8),
4271 40: ( 43.11, 88.10, -6),
4272 41: ( 25.767, 80.183, -5),
4273 42: ( 44.967, 93.25, -6),
4274 43: ( 29.95, 90.067, -6),
4275 44: ( 40.7167, 74.0167, -5),
4276 45: ( 35.483, 97.533, -6),
4277 46: ( 39.95, 75.15, -5),
4278 47: ( 33.433, 112.067,-7),
4279 48: ( 40.433, 79.9833, -5),
4280 49: ( 43.666, 70.283, -5),
4281 50: ( 45.517, 122.65, -8),
4282 51: ( 35.783, 78.65, -5),
4283 52: ( 37.5667, 77.450, -5),
4284 53: ( 38.6167, 90.1833, -6),
4285 54: ( 32.7667, 117.2167, -8),
4286 55: ( 37.7667, 122.4167, -8),
4287 56: ( 47.60, 122.3167, -8),
4288 57: ( 38.8833, 77.0333, -5),
4291 def __init__(self, sun):
4295 ct = time.localtime()
4302 luxProp(self.sun, 'sc.day', 0).set(ct[2])
4303 luxProp(self.sun, 'sc.month', 0).set(ct[1])
4304 luxProp(self.sun, 'sc.year', 0).set(ct[0])
4305 luxProp(self.sun, 'sc.hour', 0).set(ct[3])
4306 luxProp(self.sun, 'sc.minute', 0).set(ct[4])
4307 luxProp(self.sun, 'sc.dst', 0).set(dst)
4308 luxProp(self.sun, 'sc.dayminutes', 0.0).set(ct[3]*60.0+ct[4])
4312 def set_location(self, location):
4313 if location < 0: return
4315 lat, long, tz = self.location_data[location]
4316 luxProp(self.sun, "sc.lat", 0).set(lat)
4317 luxProp(self.sun, "sc.long", 0).set(long)
4318 luxProp(self.sun, "sc.tz", 0).set(tz)
4322 def compute(self, redraw=True):
4324 self.lat = luxProp(self.sun, "sc.lat", 0).get()
4325 self.long = luxProp(self.sun, "sc.long", 0).get()
4326 self.tz = luxProp(self.sun, "sc.tz", 0).get()
4328 self.hour = luxProp(self.sun, "sc.hour", 0).get()
4329 self.min = luxProp(self.sun, "sc.minute", 0).get()
4330 self.dst = luxProp(self.sun, "sc.dst", 'false').get()
4331 if self.dst == 'true':
4336 self.day = luxProp(self.sun, "sc.day", 0).get()
4337 self.month = luxProp(self.sun, "sc.month", 0).get()
4338 self.year = luxProp(self.sun, "sc.year", 0).get()
4341 az,el = self.geoSunData(
4347 self.hour + self.min/60.0,
4351 self.sun.rot = math.radians(90-el), 0, math.radians(-az)
4353 if redraw is True: Window.Redraw()
4356 # --- THE FOLLOWING METHODS ARE ADAPTED FROM LUXMAYA ---
4358 # mathematical helpers
4359 def sind(self, deg):
4360 return math.sin(math.radians(deg))
4362 def cosd(self, deg):
4363 return math.cos(math.radians(deg))
4365 def tand(self, deg):
4366 return math.tan(math.radians(deg))
4368 def asind(self, deg):
4369 return math.degrees(math.asin(deg))
4371 def atand(self, deg):
4372 return math.degrees(math.atan(deg))
4375 def geo_sun_astronomicJulianDate(self, Year, Month, Day, LocalTime, Timezone):
4377 See quoted source in class header for explanation
4387 UT = LocalTime - Timezone
4391 JD = math.floor(365.25*(Y+4716.0)) + math.floor(30.6001*(M+1.0)) + Day + hour - 1524.4
4393 # The following section is adopted from netCDF4 netcdftime implementation.
4394 # Copyright: 2008 by Jeffrey Whitaker
4395 # License: http://www.opensource.org/licenses/mit-license.php
4397 # 1582 October 15 (Gregorian Calendar)
4398 B = 2.0 - A + int(A/4.0)
4399 elif JD < 2299160.5:
4400 # 1582 October 5 (Julian Calendar)
4403 Draw.PupMenu('ERROR: Date falls in the gap between Julian and Gregorian calendars%t|OK%x1')
4408 def geoSunData(self, Latitude, Longitude, Year, Month, Day, LocalTime, Timezone):
4410 See quoted source in class header for explanation
4413 JD = self.geo_sun_astronomicJulianDate(Year, Month, Day, LocalTime, Timezone)
4419 LDeg = (280.460 + 0.9856474*n) - (math.floor((280.460 + 0.9856474*n)/360.0) * 360.0)
4420 gDeg = (357.528 + 0.9856003*n) - (math.floor((357.528 + 0.9856003*n)/360.0) * 360.0)
4421 LambdaDeg = LDeg + 1.915 * self.sind(gDeg) + 0.02 * self.sind(2.0*gDeg)
4423 epsilonDeg = 23.439 - 0.0000004*n
4425 alphaDeg = self.atand( (self.cosd(epsilonDeg) * self.sind(LambdaDeg)) / self.cosd(LambdaDeg) )
4426 if self.cosd(LambdaDeg) < 0.0:
4429 deltaDeg = self.asind( self.sind(epsilonDeg) * self.sind(LambdaDeg) )
4431 JDNull = self.geo_sun_astronomicJulianDate(Year, Month, Day, 0.0, 0.0)
4433 TNull = (JDNull - 2451545.0) / 36525.0
4434 T = LocalTime - Timezone
4436 thetaGh = 6.697376 + 2400.05134*TNull + 1.002738*T
4437 thetaGh -= math.floor(thetaGh/24.0) * 24.0
4439 thetaG = thetaGh * 15.0
4440 theta = thetaG + llambda
4442 tau = theta - alphaDeg
4444 a = self.atand( self.sind(tau) / ( self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi)) )
4445 if self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi) < 0.0:
4448 h = self.asind( self.cosd(deltaDeg)*self.cosd(tau)*self.cosd(phi) + self.sind(deltaDeg)*self.sind(phi) )
4450 R = 1.02 / (self.tand (h+(10.3/(h+5.11))))
4456 return azimuth, elevation
4458 def luxAccelerator(scn, gui=None):
4461 acceltype = luxProp(scn, "accelerator.type", "tabreckdtree")
4462 str = luxIdentifier("Accelerator", acceltype, ["none", "tabreckdtree", "grid", "bvh", "qbvh"], "ACCEL", "select accelerator type", gui)
4463 if acceltype.get() == "tabreckdtree":
4464 if gui: gui.newline()
4465 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
4466 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
4467 if gui: gui.newline()
4468 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)
4469 if gui: gui.newline()
4470 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)
4471 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)
4472 if acceltype.get() == "unsafekdtree":
4473 if gui: gui.newline()
4474 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
4475 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
4476 if gui: gui.newline()
4477 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)
4478 if gui: gui.newline()
4479 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)
4480 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)
4481 if acceltype.get() == "grid":
4482 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)
4483 if acceltype.get() == "qbvh":
4484 if gui: gui.newline()
4485 str += luxInt("maxprimsperleaf", luxProp(scn, "accelerator.qbvh.maxprimsperleaf", 4), 1, 64, "maxprimsperleaf", "Maximum number of primitives to leave in one leaf node", gui)
4488 def luxSystem(scn, gui=None):
4490 if gui: gui.newline("PATHS:", 10)
4491 lp = luxProp(scn, "lux", "")
4492 lp.set(Blender.sys.dirname(lp.get())+os.sep)
4493 luxPath("LUX dir", lp, "lux binary dir", "LuxRender installation path", gui, 2.0)
4495 # luxFile("GUI filename", luxProp(scn, "lux", ""), "lux-file", "filename and path of the lux GUI executable", gui, 2.0)
4496 # luxFile("Console filename", luxProp(scn, "luxconsole", ""), "lux-file-console", "filename and path of the lux console executable", gui, 2.0)
4497 if gui: gui.newline()
4498 datadir = luxProp(scn, "datadir", "")
4499 luxFile("datadir", datadir, "default out dir", "default.lxs save path", gui, 2.0)
4500 datadir.set(datadir.get().rstrip(os.sep))
4502 if gui: gui.newline()
4503 pm = ["absolute","relative","flat"]
4504 luxOption("pathmode", luxProp(scn, "pathmode", "absolute"), pm, "path-mode", "select format for paths on export", gui, 2.0)
4506 if gui: gui.newline("PRIORITY:", 10)
4507 luxnice = luxProp(scn, "luxnice", 10)
4508 if osys.platform=="win32":
4509 r = gui.getRect(2, 1)
4510 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))
4511 else: luxInt("nice", luxnice, -20, 19, "nice", "nice value. Range goes from -20 (highest priority) to 19 (lowest)", gui)
4513 luxBool("noopengl", luxProp(scn, "noopengl", "false"), "Disable OpenGL", "(workaround for some buggy display drivers)", gui, 1.0)
4516 if gui: gui.newline("THREADS:", 10)
4517 autothreads = luxProp(scn, "autothreads", "true")
4518 luxBool("autothreads", autothreads, "Auto Detect", "Automatically use all available processors", gui, 1.0)
4519 if autothreads.get()=="false":
4520 luxInt("threads", luxProp(scn, "threads", 1), 1, 100, "threads", "number of threads used for rendering", gui, 1.0)
4521 # luxBool('export.threaded', luxProp(scn, 'export.threaded', 'true'), 'Pipe in background', 'When using pipe export, do not block Blender UI', gui, 1.0)
4523 if gui: gui.newline("ANIM:", 10)
4524 useparamkeys = luxProp(scn, "useparamkeys", "false")
4525 luxBool("useparamkeys", useparamkeys, "Enable Parameter IPO Keyframing", "Enables keyframing of LuxBlend parameters", gui, 2.0)
4527 if gui: gui.newline("PARAMS:", 10)
4528 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
4529 luxBool("parammodeadvanced", parammodeadvanced, "Default Advanced Parameters", "Always use advanced parameters by default", gui, 2.0)
4531 if gui: gui.newline("PREVIEW:", 10)
4532 qs = ["low","medium","high","very high"]
4533 defprevmat = luxProp(scn, "defprevmat", "high")
4534 luxOption("defprevmat", defprevmat, qs, "Materials", "Select default preview quality in material editor for materials", gui, 1.0)
4536 if gui: gui.newline("GAMMA:", 10)
4537 luxBool("RGC", luxProp(scn, "RGC", "true"), "RGC", "use reverse gamma correction", gui)
4538 luxBool("ColClamp", luxProp(scn, "colorclamp", "false"), "ColClamp", "clamp all colors to 0.0-0.9", gui)
4539 if gui: gui.newline("MESH:", 10)
4540 luxBool("mesh_optimizing", luxProp(scn, "mesh_optimizing", "true"), "Optimize meshes", "Optimize meshes during export", gui, 2.0)
4541 #luxInt("trianglemesh thr", luxProp(scn, "trianglemesh_thr", 0), 0, 10000000, "trianglemesh threshold", "Vertex threshold for exporting (wald) trianglemesh object(s)", gui, 2.0)
4542 #if gui: gui.newline()
4543 #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)
4544 if gui: gui.newline("INSTANCING:", 10)
4545 luxInt("instancing_threshold", luxProp(scn, "instancing_threshold", 2), 2, 1000000, "Object instancing threshold", "Minimum number of objects to export as instances", gui, 2.0)
4547 # dougal2 packed images, enable this when implemented in Lux itself
4548 #if gui: gui.newline('TEXTURES:',10)
4549 #impack = luxProp(scn, 'packtextures', 'false')
4550 #luxBool('impack', impack, 'Pack All Images', '', gui, 2.0)
4553 network=luxProp(scn,"network","false")
4554 gui.newline("NETWORK:", 10)
4555 luxCollapse("network",network, "Network", "enable network option", gui, 2.0)
4556 if(network.get() == "true"):
4557 network_use_file=luxProp(scn,"network_use_file","false")
4558 luxBool ("use file",network_use_file,"use file", "load servers list from a file (one server per line)",gui,2.0)
4559 if (network_use_file.get() == "true"):
4560 luxFile("file", luxProp(scn, "network_file_path", ""), "file", "file with servers list (one server per line)", gui, 1.0)
4562 luxString("servers",luxProp(scn,"network_servers",""),"servers","comma-separated list of servers",gui,1.0)
4563 luxInt("network_interval",luxProp(scn,"network_interval",180),15,86400,"update interval","interval between network refresh (in seconds)",gui)
4566 def luxRemoveProps(scn, gui=None):
4567 def doRemove(defs, uids, scenes, cameras, materials, all):
4568 def wipeProps(objs):
4571 if obj.lib is not None: continue
4573 del obj.properties['luxblend']
4574 l.append('"%s"' % obj.name)
4577 return ', '.join(l) if l else 'none'
4580 scenes = scenes.get()
4581 cameras = cameras.get()
4582 materials = materials.get()
4584 if not 'true' in [defs, uids, scenes, cameras, materials]:
4585 Draw.PupMenu('ERROR: Select at least one category of properties%t|OK%x1')
4586 Blender.Window.QRedrawAll()
4588 if Draw.PupMenu(' OK?%t|Are you completely sure to remove defined LuxBlend properties? This action is irreversible.%x1') != 1:
4590 print 'Removing LuxBlend properties...'
4592 print ' - removing default settings'
4596 Blender.Registry.RemoveKey('luxblend', True)
4599 if uids == 'true' or scenes == 'true':
4600 print ' - removing UIDs'
4601 scns = filter(lambda s: s.lib is None and s != Scene.GetCurrent(), Scene.Get()) + [Scene.GetCurrent()] if all == 'true' else [Scene.GetCurrent()]
4603 luxProp(scn, 'UID', '').delete()
4604 if 'UID' in luxdefaults: del luxdefaults['UID']
4605 print ' processed scenes:', ', '.join([ '"%s"' % s.name for s in scns ])
4607 for mat in Material.Get():
4609 for volume_prop in ['Exterior', 'Interior']:
4610 luxProp(mat, '%s_vol_guid' % (volume_prop), '').delete()
4611 l.append('"%s"' % mat.name)
4612 print ' processed UID tags in materials:', (', '.join(l) if l else 'none')
4613 if scenes == 'true':
4614 print ' - removing scene properties'
4615 scns = filter(lambda s: s.lib is None and s != Scene.GetCurrent(), Scene.Get()) + [Scene.GetCurrent()] if all == 'true' else [Scene.GetCurrent()]
4616 print ' processed scenes:', wipeProps(scns)
4617 if cameras == 'true':
4618 print ' - removing camera properties'
4619 cams = Blender.Camera.Get() if all == 'true' else [Scene.GetCurrent().objects.camera.data]
4620 print ' processed cameras:', wipeProps(cams)
4621 if materials == 'true':
4622 print ' - removing material properties'
4623 print ' processed materials:', wipeProps(Material.Get())
4624 print 'LuxBlend properties removed'
4626 Blender.Window.QRedrawAll()
4629 wipe = luxProp(scn, 'wipe_props', 'false')
4630 luxCollapse('wipe', wipe, 'Reset settings', 'Completely remove LuxBlend properties from defined objects', gui, 2.0)
4631 if wipe.get() == 'true':
4632 wipe_defs = luxProp(scn, 'wipe_defs', 'false')
4633 wipe_uids = luxProp(scn, 'wipe_uids', 'false')
4634 wipe_scns = luxProp(scn, 'wipe_scns', 'false')
4635 wipe_cams = luxProp(scn, 'wipe_cams', 'false')
4636 wipe_mats = luxProp(scn, 'wipe_mats', 'false')
4637 wipe_all = luxProp(scn, 'wipe_all', 'true')
4638 luxBool('switch_wipe_defs', wipe_defs, 'Defaults', 'Reset default settings', gui, 0.5)
4639 if not wipe_scns.get() == 'true':
4640 luxBool('switch_wipe_uids', wipe_uids, 'UIDs', 'Reset scene UID (use this option after forking blend-file or making a new "Full Copy" scene)', gui, 0.25)
4641 luxBool('switch_wipe_scns', wipe_scns, 'Scenes' if wipe_scns.get() == 'true' else 'Scns', 'Remove global scene properties (including mediums definitions)', gui, 0.5 if wipe_scns.get() == 'true' else 0.25)
4642 luxBool('switch_wipe_cams', wipe_cams, 'Cameras', 'Remove camera properties', gui, 0.5)
4643 luxBool('switch_wipe_mats', wipe_mats, 'Materials', 'Remove material properties', gui, 0.5)
4644 luxBool('switch_wipe_all', wipe_all, 'All scenes/cameras', 'Remove properties from all cameras/scenes or from the current ones only', gui, 1.5)
4646 r = gui.getRect(0.5, 1)
4647 Draw.Button('REMOVE', 0, r[0], r[1], r[2], r[3], 'Proceed with removing', lambda e,v:doRemove(wipe_defs, wipe_uids, wipe_scns, wipe_cams, wipe_mats, wipe_all))
4650 def scalelist(list, factor):
4651 for i in range(len(list)): list[i] = list[i] * factor
4655 def luxMapping(key, mat, gui, level=0):
4656 global icon_map2d, icon_map2dparam
4657 if gui: gui.newline("2Dmap:", -2, level, icon_map2d)
4658 mapping = luxProp(mat, key+".mapping", "uv")
4659 mappings = ["uv","spherical","cylindrical","planar"]
4660 str = luxOption("mapping", mapping, mappings, "mapping", "", gui, 0.5)
4661 if mapping.get() == "uv":
4662 if gui: gui.newline()
4663 str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 0.5)
4664 str += luxFloat("vscale", luxProp(mat, key+".vscale", -1.0), -100.0, 100.0, "Vs", "v-scale", gui, 0.5)
4665 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.5)
4666 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 1.0 if luxProp(mat, key+'.texture', 'imagemap').get() == 'imagemap' else 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.5)
4667 elif mapping.get() == "spherical":
4668 if gui: gui.newline()
4669 str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 0.5)
4670 str += luxFloat("vscale", luxProp(mat, key+".vscale", -1.0), -100.0, 100.0, "Vs", "v-scale", gui, 0.5)
4671 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.5)
4672 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.5)
4673 elif mapping.get() == "cylindrical":
4674 if gui: gui.newline()
4675 str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 1.0)
4676 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 1.0)
4677 elif mapping.get() == "planar":
4678 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.75)
4679 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.75)
4680 if gui: gui.newline("v1:", -2, level+1, icon_map2dparam)
4681 str += luxVector("v1", luxProp(mat, key+".v1", "1 0 0"), -100.0, 100.0, "v1", "v1-vector", gui, 2.0)
4682 if gui: gui.newline("v2:", -2, level+1, icon_map2dparam)
4683 str += luxVector("v2", luxProp(mat, key+".v2", "0 1 0"), -100.0, 100.0, "v2", "v2-vector", gui, 2.0)
4686 def lux3DMapping(key, mat, gui, level=0):
4687 global icon_map3dparam
4689 if gui: gui.newline("scale:", -2, level, icon_map3dparam)
4690 str += luxVectorUniform("scale", luxProp(mat, key+".3dscale", 1.0), 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
4691 if gui: gui.newline("rot:", -2, level, icon_map3dparam)
4692 str += luxVector("rotate", luxProp(mat, key+".3drotate", "0 0 0"), -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
4693 if gui: gui.newline("move:", -2, level, icon_map3dparam)
4694 str += luxVector("translate", luxProp(mat, key+".3dtranslate", "0 0 0"), -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
4697 def getTreeNameById(tree, i): # helper function to retrive name of the selected treemenu-item
4699 if type(t)==types.TupleType:
4700 if type(t[1])==types.ListType:
4701 n=getTreeNameById(t[1], i)
4703 elif t[1]==i: return t[0]
4706 def luxTexture(name, parentkey, type, default, min, max, caption, hint, mat, gui, matlevel, texlevel=0, lightsource=0, overrideicon=""):
4707 global icon_tex, icon_texcol, icon_texmix, icon_texmixcol, icon_texparam, icon_spectex
4709 return (t1[0]+t2[0], t1[1]+t2[1])
4710 def alternativedefault(type, default):
4711 if type=="float": return 0.0
4712 else: return "0.0 0.0 0.0"
4713 level = matlevel + texlevel
4714 keyname = "%s:%s"%(parentkey, name)
4715 texname = "%s:%s"%(mat.getName(), keyname)
4716 # if gui: gui.newline(caption+":", 0, level)
4717 if(lightsource == 0):
4718 if texlevel == 0: texture = luxProp(mat, keyname+".texture", "imagemap")
4719 else: texture = luxProp(mat, keyname+".texture", "constant")
4721 texture = luxProp(mat, keyname+".texture", "blackbody")
4723 tex_all = ["constant", "imagemap", "mix", "scale", "bilerp", "brick"]
4724 tex_color = ["blackbody", "lampspectrum", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata", "tabulateddata", "uv", "harlequin", "marble"]
4725 tex_float = ["blender_marble", "blender_musgrave", "blender_wood", "blender_clouds", "blender_blend", "blender_distortednoise", "blender_noise", "blender_magic", "blender_stucci", "blender_voronoi", "checkerboard", "dots", "fbm", "windy", "wrinkled"]
4726 tex_fresnel = ['constant', 'cauchy', 'sellmeier', 'sopra', 'luxpop', 'preset']
4729 textures.extend(tex_color)
4730 textures.extend(tex_float)
4731 if type == 'fresnel':
4732 textures = tex_fresnel
4735 if(overrideicon != ""):
4739 if texture.get() in ["mix", "scale", "checkerboard", "dots"]:
4740 if type=="color": icon = icon_texmixcol
4741 else: icon = icon_texmix
4742 elif type == 'fresnel':
4744 elif texture.get() in ["constant", "blackbody", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata", "tabulateddata"]:
4747 if type=="color": icon = icon_texcol
4748 else: icon = icon_tex
4749 if (texlevel > 0): gui.newline(caption+":", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
4750 else: gui.newline("texture:", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
4751 luxOption("texture", texture, textures, "texture", "", gui, 2)
4752 if type!="float" and texture.get() in tex_float:
4753 str = "Texture \"%s::amount\" \"float\" \"%s\""%(texname, texture.get())
4755 str = "Texture \"%s\" \"%s\" \"%s\""%(texname, type, texture.get())
4757 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))
4758 if gui: # Draw Texture level Material preview
4759 luxPreview(mat, parentkey, 1, False, False, name, gui, texlevel, [0.5, 0.5, 0.5])
4760 # Add an offset for next controls
4761 #r = gui.getRect(1.0, 1)
4764 if texture.get() == "constant":
4765 value = luxProp(mat, keyname+".value", default)
4766 if type == "float": luxFloat("value", value, min, max, "", "", gui, 1.1)
4767 elif type == "color": luxRGB("value", value, max, "", "", gui, 2)
4768 elif type == 'fresnel':
4769 if gui: gui.newline()
4770 # rude copy&paste from luxIORFloatTexture() with slight modifications
4771 iorusepreset = luxProp(mat, keyname+".iorusepreset", "true")
4772 luxBool("iorusepreset", iorusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4773 if iorusepreset.get() == "true":
4774 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) ] ) ]
4775 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}
4776 iorpreset = luxProp(mat, keyname+".iorpreset", "Glass, Fused Silica" if parentkey != 'named_volumes:0.tex' else "Air @ STP")
4778 def setIor(i, value, preset, tree, dict): # callback function to set ior value after selection
4781 preset.set(getTreeNameById(tree, i))
4782 r = gui.getRect(1.6, 1)
4783 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))
4784 str += luxFloat(name, value, min, max, "IOR", hint, None, 1.6)
4786 str += luxFloat(name, value, min, max, "IOR", 'Uniform index of refraction', gui, 1.6, 1)
4787 return str, ' "texture %s" ["%s"]' % (type, texname)
4789 if type == "color": return ("", " \"%s %s\" [%s]"%(type, name, value.getRGC()))
4790 return ("", " \"%s %s\" [%s]"%(type, name, value.get()))
4792 # if type == "color": str += " \"%s value\" [%s]"%(type, value.getRGC())
4793 # else: str += " \"%s value\" [%s]"%(type, value.get())
4795 if texture.get() == 'cauchy':
4796 if gui: gui.newline()
4797 cauchya = luxProp(mat, keyname+'.cauchya.value', 1.4580)
4798 cauchyb = luxProp(mat, keyname+'.cauchyb.value', 0.00354)
4799 # copy&paste from luxCauchyBFloatTexture() with some modifications
4800 cauchynames = ["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" ]
4801 cauchyvals = [ (1.4580, 0.00354), (1.5046, 0.00420), (1.5220, 0.00459), (1.5690, 0.00531), (1.6700, 0.00743), (1.7280, 0.01342) ]
4802 cauchyusepreset = luxProp(mat, keyname+".cauchyusepreset", "true")
4803 cauchyindex = luxProp(mat, keyname+'.cauchyindex', 'false')
4804 luxBool("cauchyusepreset", cauchyusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4806 if cauchyusepreset.get() == "true":
4807 cauchypreset = luxProp(mat, keyname+".cauchypreset", "01 - Fused silica glass")
4808 luxOption("cauchypreset", cauchypreset, cauchynames, " PRESET", "Select Cauchy preset", gui, 1.6)
4809 idx = cauchynames.index(cauchypreset.get())
4810 cauchyindex.set('false')
4811 cauchya.set(cauchyvals[idx][0])
4812 cauchyb.set(cauchyvals[idx][1])
4813 str += luxFloat('cauchya', cauchya, min, max, 'cauchy a', hint, None)
4814 str += luxFloat('cauchyb', cauchyb, 0.0, 1.0, 'cauchy b', hint, None)
4816 luxBool('cauchyindex', cauchyindex, 'Index', 'Use IOR value instead of Cauchy\'s A', gui, 0.4)
4817 if cauchyindex.get() == 'true':
4818 str += luxFloat('index', luxProp(mat, keyname+'.value', 1.459), min, max, 'ior', 'Index of refraction', gui, 0.6)
4820 str += luxFloat('cauchya', cauchya, min, max, 'a', 'Cauchy\'s A parameter', gui, 0.6)
4821 str += luxFloat('cauchyb', cauchyb, 0.0, 1.0, 'b', 'Cauchy\'s B parameter', gui, 0.6)
4822 return str, ' "texture %s" ["%s"]' % (type, texname)
4824 if texture.get() == 'sellmeier':
4825 def sellmeierStrToFloats(sb, sc, min, max):
4830 for i in s.split(' '):
4832 if len(i): vars()['f'+l].append(sorted([float(i),min,max])[1])
4834 print 'WARNING: Illegal value dropped from sellmeier texture: only floats are allowed'
4835 if len(fb) > len(fc):
4836 fc.extend([0.0] * (len(fb) - len(fc)))
4837 elif len(fc) > len(fb):
4840 if gui: gui.newline()
4841 sellmeiernames = [ '01 - Fused silica', '02 - Borosilicate glass BK7', '03 - Sapphire (ordinary wave)', '04 - Sapphire (extraordinary wave)' ]
4842 sellmeiervals = [ (1.0, '0.696166300 0.407942600 0.897479400', '4.67914826e-3 1.35120631e-2 97.9340025'), (1.0, '1.03961212 0.231792344 1.01046945', '6.00069867e-3 2.00179144e-2 1.03560653e2'), (1.0, '1.43134930 0.65054713 5.3414021', '5.2799261e-3 1.42382647e-2 3.25017834e2'), (1.0, '1.5039759 0.55069141 6.5927379', '5.48041129e-3 1.47994281e-2 4.0289514e2') ]
4843 sellmeiera = luxProp(mat, keyname+'.sellmeiera.value', sellmeiervals[0][0])
4844 sellmeierb = luxProp(mat, keyname+'.sellmeierb.value', sellmeiervals[0][1])
4845 sellmeierc = luxProp(mat, keyname+'.sellmeierc.value', sellmeiervals[0][2])
4846 sellmeierb1 = luxProp(mat, keyname+'.sellmeierb1.value', float(sellmeiervals[0][1].split(' ')[0]))
4847 sellmeierb2 = luxProp(mat, keyname+'.sellmeierb2.value', float(sellmeiervals[0][1].split(' ')[1]))
4848 sellmeierb3 = luxProp(mat, keyname+'.sellmeierb3.value', float(sellmeiervals[0][1].split(' ')[2]))
4849 sellmeierc1 = luxProp(mat, keyname+'.sellmeierc1.value', float(sellmeiervals[0][2].split(' ')[0]))
4850 sellmeierc2 = luxProp(mat, keyname+'.sellmeierc2.value', float(sellmeiervals[0][2].split(' ')[1]))
4851 sellmeierc3 = luxProp(mat, keyname+'.sellmeierc3.value', float(sellmeiervals[0][2].split(' ')[2]))
4852 sellmeieradvanced = luxProp(mat, keyname+'sellmeieradvanced', 'false')
4853 sellmeierusepreset = luxProp(mat, keyname+'.sellmeierusepreset', 'true')
4854 luxBool('sellmeierusepreset', sellmeierusepreset, 'Preset', 'Select from a list of predefined presets', gui, 0.4)
4856 if sellmeierusepreset.get() == 'true':
4857 sellmeierpreset = luxProp(mat, keyname+'.sellmeierpreset', sellmeiernames[0])
4858 luxOption('sellmeierpreset', sellmeierpreset, sellmeiernames, ' PRESET', 'Select Sellmeier preset', gui, 1.6)
4859 idx = sellmeiernames.index(sellmeierpreset.get())
4860 sellmeiera.set(sellmeiervals[idx][0])
4861 sellmeierb.set(sellmeiervals[idx][1])
4862 sellmeierc.set(sellmeiervals[idx][2])
4863 sellmeierb1.set(float(sellmeiervals[idx][1].split(' ')[0]))
4864 sellmeierb2.set(float(sellmeiervals[idx][1].split(' ')[1]))
4865 sellmeierb3.set(float(sellmeiervals[idx][1].split(' ')[2]))
4866 sellmeierc1.set(float(sellmeiervals[idx][2].split(' ')[0]))
4867 sellmeierc2.set(float(sellmeiervals[idx][2].split(' ')[1]))
4868 sellmeierc3.set(float(sellmeiervals[idx][2].split(' ')[2]))
4869 str += luxFloat('A', sellmeiera, 0.001, 10.0, 'sellmeier a', 'Sellmeier\'s A parameter (constant, usually 1.0)', None)
4871 luxBool('sellmeieradvanced', sellmeieradvanced, 'Advanced', 'Advanced parameters', gui, 1.6 if sellmeieradvanced.get() == 'false' else 0.6)
4872 if sellmeieradvanced.get() == 'false':
4873 str += luxFloat('A', sellmeiera, 0.001, 10.0, 'sellmeier a', 'Sellmeier\'s A parameter (constant, usually 1.0)', None)
4874 luxFloat('B1', sellmeierb1, 0, 99.9, 'b', 'Sellmeier\'s first B parameter', gui, 0.66)
4875 luxFloat('B2', sellmeierb2, 0, 99.9, 'b', 'Sellmeier\'s second B parameter', gui, 0.66)
4876 luxFloat('B3', sellmeierb3, 0, 99.9, 'b', 'Sellmeier\'s third B parameter', gui, 0.66)
4877 luxFloat('C1', sellmeierc1, 0, 9.9, 'c', 'Sellmeier\'s first C parameter', gui, 0.66)
4878 luxFloat('C2', sellmeierc2, 0, 9.9, 'c', 'Sellmeier\'s second C parameter', gui, 0.66)
4879 luxFloat('C3', sellmeierc3, 0, 999.9, 'c', 'Sellmeier\'s third C parameter', gui, 0.66)
4880 sellmeierb.set(' '.join([__builtins__['str'](sellmeierb1.get()), types.StringType(sellmeierb2.get()), types.StringType(sellmeierb3.get())]))
4881 sellmeierc.set(' '.join([__builtins__['str'](sellmeierc1.get()), types.StringType(sellmeierc2.get()), types.StringType(sellmeierc3.get())]))
4883 str += luxFloat('A', sellmeiera, 0.001, 10.0, 'sellmeier a', 'Sellmeier\'s A parameter (constant, usually 1.0)', gui, 1.0)
4884 luxString('sellmeierb', sellmeierb, 'sellmeier b', 'Sellmeier\'s B parameter (space-separated list of floats)', gui,2.0)
4885 luxString('sellmeierc', sellmeierc, 'sellmeier c', 'Sellmeier\'s C parameter (space-separated list of floats; same number of floats as in B above)', gui,2.0)
4887 (listb, listc) = sellmeierStrToFloats(sellmeierb.get(), sellmeierc.get(), 0, 10000.0)
4888 sellmeierb.set(' '.join(map(lambda x: types.StringType(x), listb)))
4889 sellmeierc.set(' '.join(map(lambda x: types.StringType(x), listc)))
4890 str += "\n \"float B\" [%s]" % sellmeierb.get()
4891 str += "\n \"float C\" [%s]" % sellmeierc.get()
4892 return str, ' "texture %s" ["%s"]' % (type, texname)
4894 if texture.get() == 'preset':
4895 preset = luxProp(mat, keyname+'.preset', '')
4896 presets = ['aluminium', 'amorphous carbon', 'silver', 'gold', 'copper']
4897 str += luxOption('name', preset, presets, ' PRESET', 'Select preset from the list', gui, 2.0)
4898 return str, ' "texture %s" ["%s"]' % (type, texname)
4900 if texture.get() == "blackbody":
4902 if gui.xmax-gui.x < gui.w: gui.newline()
4903 r = gui.getRect(1.0, 1)
4905 drawBar(bar_blackbody, gui.xmax-gui.w-7, r[1])
4906 str += luxFloat("temperature", luxProp(mat, keyname+".bbtemp", 6500.0), 1000.0, 10000.0, "temperature", "Black Body temperature in degrees Kelvin", gui, 2.0, 1)
4908 if texture.get() == "lampspectrum":
4909 lampstring = luxProp(mat, keyname+".lampstring", "Incandescent2")
4910 lamppreset = luxProp(mat, keyname+".lampspectrum", "PHILIPS [Argenta] 200W Incandescent Lamp")
4912 def setLamp(i, value, preset, tree, dict): # callback function to set ior value after selection
4915 preset.set(getTreeNameById(tree, i))
4917 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) ] ) ]
4919 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" }
4921 r = gui.getRect(2.0, 1)
4922 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))
4923 str += luxString("name", lampstring, "Lamp", "Choose measured Lamp Spectrum", None, 2.0)
4925 if texture.get() == "equalenergy":
4927 if gui.xmax-gui.x < gui.w: gui.newline()
4928 r = gui.getRect(1.0, 1)
4930 drawBar(bar_equalenergy, gui.xmax-gui.w-7, r[1])
4931 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Energy of each spectral band", gui, 2.0, 1)
4933 if texture.get() == "frequency":
4934 str += luxFloat("freq", luxProp(mat, keyname+".freq", 0.01), 0.01, 100.0, "frequency", "Frequency in nm", gui, 2.0, 1)
4935 str += luxFloat("phase", luxProp(mat, keyname+".phase", 0.5), 0.0, 1.0, "phase", "Phase", gui, 1.1, 1)
4936 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
4938 if texture.get() == "gaussian":
4940 if gui.xmax-gui.x < gui.w: gui.newline()
4941 r = gui.getRect(1.0, 1)
4943 drawBar(bar_spectrum, gui.xmax-gui.w-7, r[1])
4944 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)
4945 str += luxFloat("width", luxProp(mat, keyname+".width", 50.0), 20.0, 300.0, "width", "Width of gaussian distribution in nm", gui, 1.1, 1)
4946 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
4948 if texture.get() in ["tabulateddata", "sopra", "luxpop"]:
4949 if gui: gui.newline("data file:", -2, level)
4950 str += luxFile("filename", luxProp(mat, keyname+".filename", ""), "file", "data file path", gui, 2.0)
4951 if type == 'fresnel':
4952 return str, ' "texture %s" ["%s"]' % (type, texname)
4954 if texture.get() == "imagemap":
4955 if gui: gui.newline("IM-clip:", -2, level)
4956 str += luxOption("wrap", luxProp(mat, keyname+".wrap", "repeat"), ["repeat","black","clamp"], "repeat", "", gui, 1.0)
4958 str += luxOption("channel", luxProp(mat, keyname+".channel", "mean"), ["red", "green", "blue", "alpha", "mean", "colored_mean"], "channel", "Image channel", gui, 1.0)
4960 if gui: gui.newline("IM-source:", -2, level)
4963 texturefilename = luxProp(mat, keyname+".filename", "")
4964 extimage = luxProp(mat, keyname+'.externalimage', "true")
4965 luxBool("External Image", extimage, "External Image", "External Image", gui, 1.0)
4966 if gui: gui.newline("IM-path:", -2, level)
4967 if extimage.get() == "true":
4968 luxFile("filename", texturefilename, "file", "texture file path", gui, 2.0)
4970 bil = [i.filename for i in Image.Get() if '.' in i.filename]
4972 uti = [i.filename for i in Image.Get() if '.' not in i.filename]
4974 luxLabel("INFO: Images not listed here must be saved first", gui)
4977 luxOption("Image", texturefilename, bil, "Blender Images", "Blender Image", gui, 2.0)
4979 luxLabel("No Blender Images - Load Image in the Image Editor", gui)
4980 # dougal2 image file packing
4981 impack = luxProp(Scene.GetCurrent(), 'packtextures', 'false')
4983 if impack.get() == 'false':
4984 str += luxFile("filename", texturefilename, "file", "texture file path", None, 2.0)
4987 def get_image_data(filename):
4989 f=open(filename,'rb')
4993 print('Error reading image data from %s' % filename)
4995 return base64.b64encode(zlib.compress(d))
4996 imdata = get_image_data(texturefilename.get())
4997 str += '\r\n "string imagedata" ["%s"]' % imdata
4999 useseq = luxProp(mat, keyname+".useseq", "false")
5000 luxCollapse("usesew", useseq, "Sequence", "", gui, 2.0)
5002 if useseq.get() == "true":
5003 seqframes = luxProp(mat, keyname+".seqframes", 100)
5004 luxInt("frames", seqframes, 1, 100000, "Frames", "", gui, 0.5)
5005 seqoffset = luxProp(mat, keyname+".seqoffset", 0)
5006 luxInt("offset", seqoffset, 0, 100000, "Offset", "", gui, 0.5)
5007 seqstartframe = luxProp(mat, keyname+".seqsframe", 1)
5008 luxInt("startframe", seqstartframe, 1, 100000, "StartFr", "", gui, 0.5)
5009 seqcyclic = luxProp(mat, keyname+".seqcycl", "false")
5010 luxBool("cyclic", seqcyclic, "Cyclic", "", gui, 0.5)
5013 totalframes = seqframes.get()
5014 currentframe = Blender.Get('curframe')
5016 if(currentframe < seqstartframe.get()):
5017 fnumber = 1 + seqoffset.get()
5019 fnumber = (currentframe - (seqstartframe.get()-1)) + seqoffset.get()
5021 if(fnumber > seqframes.get()):
5022 if(seqcyclic.get() == "false"):
5023 fnumber = seqframes.get()
5025 fnumber = currentframe % seqframes.get()
5028 def get_seq_filename(number, filename):
5029 m = re.findall(r'(\d+)', filename)
5031 return "ERR: Can't find pattern"
5033 rightmost_number = m[len(m)-1]
5034 seq_length = len(rightmost_number)
5037 new_seq_number = nstr.zfill(seq_length)
5039 return filename.replace(rightmost_number, new_seq_number)
5041 texturefilename.set(get_seq_filename(fnumber, texturefilename.get()))
5042 if gui: gui.newline()
5044 str += luxFloat("gamma", luxProp(mat, keyname+".gamma", texturegamma()), 0.0, 6.0, "gamma", "", gui, 0.75)
5045 str += luxFloat("gain", luxProp(mat, keyname+".gain", 1.0), 0.0, 10.0, "gain", "", gui, 0.5)
5046 filttype = luxProp(mat, keyname+".filtertype", "bilinear")
5047 filttypes = ["mipmap_ewa","mipmap_trilinear","bilinear","nearest"]
5048 str += luxOption("filtertype", filttype, filttypes, "filtertype", "Choose the filtering method to use for the image texture", gui, 0.75)
5050 if filttype.get() == "mipmap_ewa" or filttype.get() == "mipmap_trilinear":
5051 str += luxFloat("maxanisotropy", luxProp(mat, keyname+".maxanisotropy", 8.0), 1.0, 512.0, "maxaniso", "", gui, 1.0)
5052 str += luxInt("discardmipmaps", luxProp(mat, keyname+".discardmipmaps", 0), 0, 1, "discardmips", "", gui, 1.0)
5054 str += luxMapping(keyname, mat, gui, level+1)
5056 if texture.get() == "mix":
5057 (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))
5058 (s, l) = c((s, l), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5059 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5062 if texture.get() == "scale":
5063 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5064 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5067 if texture.get() == "bilerp":
5069 str += luxFloat("v00", luxProp(mat, keyname+".v00", 0.0), min, max, "v00", "", gui, 1.0)
5070 str += luxFloat("v01", luxProp(mat, keyname+".v01", 1.0), min, max, "v01", "", gui, 1.0)
5071 if gui: gui.newline("", -2)
5072 str += luxFloat("v10", luxProp(mat, keyname+".v10", 0.0), min, max, "v10", "", gui, 1.0)
5073 str += luxFloat("v11", luxProp(mat, keyname+".v11", 1.0), min, max, "v11", "", gui, 1.0)
5074 elif type == "color":
5075 if gui: gui.newline(" v00:", -2)
5076 str += luxRGB("v00", luxProp(mat, keyname+".v00", "0.0 0.0 0.0"), max, "v00", "", gui, 2.0)
5077 if gui: gui.newline(" v01:", -2)
5078 str += luxRGB("v01", luxProp(mat, keyname+".v01", "1.0 1.0 1.0"), max, "v01", "", gui, 2.0)
5079 if gui: gui.newline(" v10:", -2)
5080 str += luxRGB("v10", luxProp(mat, keyname+".v10", "0.0 0.0 0.0"), max, "v10", "", gui, 2.0)
5081 if gui: gui.newline(" v11:", -2)
5082 str += luxRGB("v11", luxProp(mat, keyname+".v11", "1.0 1.0 1.0"), max, "v11", "", gui, 2.0)
5083 str += luxMapping(keyname, mat, gui, level+1)
5085 if texture.get() == "windy":
5086 str += lux3DMapping(keyname, mat, gui, level+1)
5087 # this texture has no options
5090 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5091 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5092 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5095 if texture.get() == "checkerboard":
5096 dim = luxProp(mat, keyname+".dim", 2)
5097 str += luxInt("dimension", dim, 2, 3, "dim", "", gui, 1)
5098 if dim.get() == 2: str += luxOption("aamode", luxProp(mat, keyname+".aamode", "closedform"), ["closedform","supersample","none"], "aamode", "antialiasing mode", gui, 0.6)
5099 if gui: gui.newline("", -2)
5100 if dim.get() == 2: str += luxMapping(keyname, mat, gui, level+1)
5101 if dim.get() == 3: str += lux3DMapping(keyname, mat, gui, level+1)
5104 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5106 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5107 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5110 if texture.get() == "dots":
5111 str += luxMapping(keyname, mat, gui, level+1)
5114 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5116 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "inside", "", mat, gui, matlevel, texlevel+1, lightsource))
5117 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "outside", "", mat, gui, matlevel, texlevel+1, lightsource))
5120 if texture.get() == "fbm":
5121 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
5122 # if gui: gui.newline("", -2)
5123 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
5124 if gui: gui.newline("", -2)
5125 str += lux3DMapping(keyname, mat, gui, level+1)
5128 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5129 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5130 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5133 if texture.get() == "marble":
5134 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
5135 # if gui: gui.newline("", -2)
5136 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
5137 if gui: gui.newline("", -2)
5138 str += luxFloat("nscale", luxProp(mat, keyname+".nscale", 1.0), 0.0, 100.0, "nscale", "Scaling factor for the noise input", gui, 1.0)
5139 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)
5140 if gui: gui.newline("", -2)
5141 str += lux3DMapping(keyname, mat, gui, level+1)
5143 if texture.get() == "wrinkled":
5144 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
5145 # if gui: gui.newline("", -2)
5146 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
5147 if gui: gui.newline("", -2)
5148 str += lux3DMapping(keyname, mat, gui, level+1)
5151 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5152 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5153 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5156 if texture.get() == "brick":
5157 bonds = ["stacked","running", "flemish", "english", "herringbone", "basket", "chain link"]
5158 bond = luxProp(mat, keyname+".brickbond", "running")
5159 running = ["running","flemish"]
5160 defaultrun = {"running":0.5,"flemish":0.75}
5161 pavers = ["basket","herringbone"]
5163 if gui: gui.newline("brick:", -2, level+1, icon_texparam)
5165 str += luxFloat("brickwidth", luxProp(mat, keyname+".brickwidth", 0.3), 0.0, 10.0, "brickwidth (X)", "", gui, 1.0)
5166 str += luxFloat("brickheight", luxProp(mat, keyname+".brickheight", 0.1), 0.0, 10.0, "brickheight (Z)", "", gui, 1.0)
5167 str += luxFloat("brickdepth", luxProp(mat, keyname+".brickdepth", 0.15), 0.0, 10.0, "brickdepth (Y)", "", gui, 1.0)
5169 if gui: gui.newline("mortar:", -2, level+1, icon_texparam)
5171 str += luxFloat("mortarsize", luxProp(mat, keyname+".mortarsize", 0.01), 0.0, 1.0, "mortarsize", "", gui, 1.0)
5173 if gui: gui.newline("bond:", -2, level+1, icon_texparam)
5174 str += luxOption("brickbond", bond, bonds, "bond", "", gui, 0.5)
5175 if bond.get() in running:
5176 str += luxFloat("brickrun", luxProp(mat, keyname+".brickrun", defaultrun[bond.get()]), -10.0, 10.0, "brickrun", "", gui, 1.0)
5177 if bond.get() in pavers and gui:
5178 gui.newline("This paving bond is only mapped to xy",-2,level+7);
5180 (s, l) = c(("", ""), luxTexture("bricktex", keyname, type, default, min, max, "bricktex", "", mat, gui, matlevel, texlevel+1, lightsource))
5181 (s, l) = c((s, l), luxTexture("mortartex", keyname, type, alternativedefault(type, default), min, max, "mortartex", "", mat, gui, matlevel, texlevel+1, lightsource))
5182 (s, l) = c((s, l), luxTexture("brickmodtex", keyname, type, default, min, max, "modulation", "", mat, gui, matlevel, texlevel+1, lightsource))
5185 str += lux3DMapping(keyname, mat, gui, level+1)
5187 if texture.get() == "blender_marble":
5188 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5190 mtype = luxProp(mat, keyname+".mtype", "soft")
5191 mtypes = ["soft","sharp","sharper"]
5192 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
5194 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
5195 noisetypes = ["soft_noise","hard_noise"]
5196 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
5198 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 0.75)
5200 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5201 str += luxFloat("turbulence", luxProp(mat, keyname+".turbulence", 5.0), 0.0, 200.0, "turbulence", "", gui, 1.0)
5203 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
5204 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
5205 noisebasises2 = ["sin","saw","tri"]
5206 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
5208 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5209 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5210 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
5212 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5213 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5214 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5216 str += lux3DMapping(keyname, mat, gui, level+1)
5219 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5221 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5222 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5225 if texture.get() == "blender_musgrave":
5226 if gui: gui.newline("type:", -2, level+1, icon_texparam)
5227 mtype = luxProp(mat, keyname+".mtype", "multifractal")
5228 mtypes = ["multifractal","ridged_multifractal", "hybrid_multifractal", "hetero_terrain", "fbm"]
5229 str += luxOption("type", mtype, mtypes, "type", "", gui, 2.0)
5231 str += luxFloat("h", luxProp(mat, keyname+".h", 1.0), 0.0, 2.0, "h", "", gui, 0.5)
5232 str += luxFloat("lacu", luxProp(mat, keyname+".lacu", 2.0), 0.0, 6.0, "lacu", "", gui, 0.75)
5233 str += luxFloat("octs", luxProp(mat, keyname+".octs", 2.0), 0.0, 8.0, "octs", "", gui, 0.75)
5235 if mtype.get() == "hetero_terrain":
5236 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 2.0)
5237 if mtype.get() == "ridged_multifractal":
5238 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
5239 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
5240 if mtype.get() == "hybrid_multifractal":
5241 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
5242 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
5244 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.0, 10.0, "iscale", "", gui, 1.0)
5245 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5247 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
5248 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5249 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5250 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 2.0)
5252 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5253 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5254 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5256 str += lux3DMapping(keyname, mat, gui, level+1)
5259 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5261 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5262 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5265 if texture.get() == "blender_wood":
5266 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5268 mtype = luxProp(mat, keyname+".mtype", "bands")
5269 mtypes = ["bands","rings","bandnoise", "ringnoise"]
5270 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
5272 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
5273 noisetypes = ["soft_noise","hard_noise"]
5274 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
5276 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5277 str += luxFloat("turbulence", luxProp(mat, keyname+".turbulence", 5.0), 0.0, 200.0, "turbulence", "", gui, 1.0)
5279 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
5280 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
5281 noisebasises2 = ["sin","saw","tri"]
5282 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
5284 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5285 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5286 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
5288 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5289 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5290 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5292 str += lux3DMapping(keyname, mat, gui, level+1)
5295 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5297 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5298 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5301 if texture.get() == "blender_clouds":
5302 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5304 mtype = luxProp(mat, keyname+".mtype", "default")
5305 mtypes = ["default","color"]
5306 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
5308 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
5309 noisetypes = ["soft_noise","hard_noise"]
5310 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
5312 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5313 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 1.0)
5315 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
5316 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5317 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5318 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
5320 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5321 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5322 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5324 str += lux3DMapping(keyname, mat, gui, level+1)
5327 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5329 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5330 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5333 if texture.get() == "blender_blend":
5334 if gui: gui.newline("type:", -2, level+1, icon_texparam)
5336 mtype = luxProp(mat, keyname+".mtype", "lin")
5337 mtypes = ["lin","quad","ease","diag","sphere","halo","radial"]
5338 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
5340 mflag = luxProp(mat, keyname+".flag", "false")
5341 str += luxBool("flipxy", mflag, "flipXY", "", gui, 0.5)
5343 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5344 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5345 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5347 str += lux3DMapping(keyname, mat, gui, level+1)
5350 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5352 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5353 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5356 if texture.get() == "blender_distortednoise":
5357 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5359 str += luxFloat("distamount", luxProp(mat, keyname+".distamount", 1.0), 0.0, 10.0, "distamount", "", gui, 1.0)
5360 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5361 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.000, 2.0, "nabla", "", gui, 1.0)
5363 if gui: gui.newline("distortion:", -2, level+1, icon_texparam)
5364 ntype = luxProp(mat, keyname+".type", "blender_original")
5365 ntypes = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5366 str += luxOption("type", ntype, ntypes, "type", "", gui, 1.3)
5368 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
5369 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5370 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5371 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
5373 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5374 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5375 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5377 str += lux3DMapping(keyname, mat, gui, level+1)
5380 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5382 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5383 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5386 if texture.get() == "blender_noise":
5387 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5388 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5389 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5391 str += lux3DMapping(keyname, mat, gui, level+1)
5394 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5396 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5397 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5400 if texture.get() == "blender_magic":
5401 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5403 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0.0, 10.0, "noisedepth", "", gui, 1.0)
5404 str += luxFloat("turbulence", luxProp(mat, keyname+".turbulence", 5.0), 0.0, 200.0, "turbulence", "", gui, 1.0)
5406 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5407 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5408 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5410 str += lux3DMapping(keyname, mat, gui, level+1)
5413 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5415 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5416 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5419 if texture.get() == "blender_stucci":
5420 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
5421 mtype = luxProp(mat, keyname+".mtype", "Plastic")
5422 mtypes = ["Plastic","Wall In","Wall Out"]
5423 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
5425 noisetype = luxProp(mat, keyname+".noisetype", "soft_noise")
5426 noisetypes = ["soft_noise","hard_noise"]
5427 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
5429 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 10.0, "noisesize", "", gui, 1.0)
5430 str += luxFloat("turbulence", luxProp(mat, keyname+".turbulence", 5.0), 0.0, 200.0, "turbulence", "", gui, 1.0)
5432 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
5433 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
5434 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
5436 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5437 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5438 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5440 str += lux3DMapping(keyname, mat, gui, level+1)
5443 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5445 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5446 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5449 if texture.get() == "blender_voronoi":
5450 #if gui: gui.newline("distmetric:", -2, level+1, icon_texparam)
5451 mtype = luxProp(mat, keyname+".distmetric", "actual_distance")
5452 mtypes = ["actual_distance","distance_squared","manhattan", "chebychev", "minkovsky_half", "minkovsky_four", "minkovsky"]
5453 str += luxOption("distmetric", mtype, mtypes, "distmetric", "", gui, 1.1)
5455 if gui: gui.newline("param:", -2, level+1, icon_texparam)
5456 str += luxFloat("minkovsky_exp", luxProp(mat, keyname+".minkovsky_exp", 2.5), 0.001, 10.0, "minkovsky_exp", "", gui, 1.0)
5457 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.01, 10.0, "outscale", "", gui, 1.0)
5458 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
5459 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.001, 0.1, "nabla", "", gui, 1.0)
5460 if gui: gui.newline("wparam:", -2, level+1, icon_texparam)
5461 str += luxFloat("w1", luxProp(mat, keyname+".w1", 1.0), -2.0, 2.0, "w1", "", gui, 1.0)
5462 str += luxFloat("w2", luxProp(mat, keyname+".w2", 0.0), -2.0, 2.0, "w2", "", gui, 1.0)
5463 str += luxFloat("w3", luxProp(mat, keyname+".w3", 0.0), -2.0, 2.0, "w3", "", gui, 1.0)
5464 str += luxFloat("w4", luxProp(mat, keyname+".w4", 0.0), -2.0, 2.0, "w4", "", gui, 1.0)
5466 if gui: gui.newline("level:", -2, level+1, icon_texparam)
5467 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
5468 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
5470 str += lux3DMapping(keyname, mat, gui, level+1)
5473 str += "Texture \"%s\" \"%s\" \"mix\" \"texture amount\" [\"%s::amount\"]"%(texname, type, texname)
5475 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
5476 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
5479 return (str+"\n", " \"texture %s\" [\"%s\"]"%(name, texname))
5482 def luxSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
5484 if gui: gui.newline(caption, 4, level, icon_col, scalelist([0.5,0.6,0.5],2.0/(level+2)))
5486 keyname = "%s:%s"%(key, name)
5487 texname = "%s:%s"%(mat.getName(), keyname)
5488 value = luxProp(mat, keyname, default)
5489 link = luxRGB(name, value, max, "", hint, gui, 2.0)
5490 tex = luxProp(mat, keyname+".textured", False)
5491 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)]))
5492 if tex.get()=="true":
5493 if gui: gui.newline("", -2)
5494 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1)
5495 if value.getRGB() != (1.0, 1.0, 1.0):
5496 if str == "": # handle special case if texture is a just a constant
5497 str += "Texture \"%s\" \"color\" \"scale\" \"color tex1\" [%s] \"color tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
5498 else: str += "Texture \"%s\" \"color\" \"scale\" \"texture tex1\" [\"%s\"] \"color tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5499 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5502 def luxLightSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
5503 #if gui: gui.newline(caption, 4, level, icon_emission, scalelist([0.6,0.5,0.5],2.0/(level+2)))
5505 keyname = "%s:%s"%(key, name)
5506 texname = "%s:%s"%(mat.getName(), keyname)
5507 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1, 0, 1)
5510 def luxFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5512 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5514 keyname = "%s:%s"%(key, name)
5515 texname = "%s:%s"%(mat.getName(), keyname)
5516 value = luxProp(mat, keyname, default)
5517 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
5518 tex = luxProp(mat, keyname+".textured", False)
5519 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)]))
5520 if tex.get()=="true":
5521 if gui: gui.newline("", -2)
5522 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5523 if value.get() != 1.0:
5524 if str == "": # handle special case if texture is a just a constant
5525 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
5526 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5527 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5530 def luxFloatSliderTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5532 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5534 keyname = "%s:%s"%(key, name)
5535 texname = "%s:%s"%(mat.getName(), keyname)
5536 value = luxProp(mat, keyname, default)
5537 link = luxFloat(name, value, min, max, caption, hint, gui, 2.0, 1)
5538 tex = luxProp(mat, keyname+".textured", False)
5539 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)]))
5540 if tex.get()=="true":
5541 if gui: gui.newline("", -2)
5542 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5543 if value.get() != 1.0:
5544 if str == "": # handle special case if texture is a just a constant
5545 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
5546 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5547 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5551 def luxExponentTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5553 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5555 keyname = "%s:%s"%(key, name)
5556 texname = "%s:%s"%(mat.getName(), keyname)
5557 value = luxProp(mat, keyname, default)
5559 if(value.get() == None): value.set(0.002)
5561 # link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
5563 r = gui.getRect(2.0, 1)
5564 Draw.Number("", evtLuxGui, r[0], r[1], r[2], r[3], float(2.0/(value.getFloat() ** 2)-2.0), 1.0, 1000000.0, hint, lambda e,v: value.set(math.sqrt(2.0/(v+2.0))))
5565 link = " \"float %s\" [%f]"%(name, value.getFloat())
5567 tex = luxProp(mat, keyname+".textured", False)
5568 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)]))
5569 if tex.get()=="true":
5570 if gui: gui.newline("", -2)
5571 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5572 if value.get() != 1.0:
5573 if str == "": # handle special case if texture is a just a constant
5574 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
5575 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5576 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5580 def luxDispFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5582 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5584 keyname = "%s:%s"%(key, name)
5585 texname = "%s:%s"%(mat.getName(), keyname)
5586 value = luxProp(mat, keyname, default)
5587 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
5588 tex = luxProp(mat, keyname+".textured", False)
5589 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)]))
5590 if tex.get()=="true":
5591 if gui: gui.newline("", -2)
5592 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5593 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5594 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5597 def luxIORFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5599 iornames = ["0Z *** Gases @ 0 C ***", "01 - Vacuum", "02 - Air @ STP", "03 - Air", "04 - Helium", "05 - Hydrogen", "06 - Carbon dioxide",
5600 "1Z *** LIQUIDS @ 20 C ***", "11 - Benzene", "12 - Water", "13 - Ethyl alcohol", "14 - Carbon tetrachloride", "15 - Carbon disulfide",
5601 "2Z *** SOLIDS at room temperature ***", "21 - Diamond", "22 - Strontium titanate", "23 - Amber", "24 - Fused silica glass", "25 - sodium chloride",
5602 "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"]
5603 iorvals = [1.0, 1.0, 1.0002926, 1.000293, 1.000036, 1.000132, 1.00045,
5604 1.501, 1.501, 1.333, 1.361, 1.461, 1.628,
5605 2.419, 2.419, 2.41, 1.55, 1.458, 1.50,
5606 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]
5609 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5611 keyname = "%s:%s"%(key, name)
5612 texname = "%s:%s"%(mat.getName(), keyname)
5613 value = luxProp(mat, keyname, default)
5615 iorusepreset = luxProp(mat, keyname+".iorusepreset", "true")
5616 luxBool("iorusepreset", iorusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
5618 if(iorusepreset.get() == "true"):
5619 iorpreset = luxProp(mat, keyname+".iorpreset", "Glass, Fused Silica")
5621 def setIor(i, value, preset, tree, dict): # callback function to set ior value after selection
5624 preset.set(getTreeNameById(tree, i))
5625 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) ] ) ]
5626 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}
5627 r = gui.getRect(1.6, 1)
5628 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))
5629 link = luxFloat(name, value, min, max, "IOR", hint, None, 1.6)
5631 link = luxFloat(name, value, min, max, "IOR", hint, gui, 1.6, 1)
5633 tex = luxProp(mat, keyname+".textured", False)
5634 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)]))
5635 if tex.get()=="true":
5636 if gui: gui.newline("", -2)
5637 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5638 if value.get() != 1.0:
5639 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5640 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5643 def luxCauchyBFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
5645 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" ]
5646 cauchybvals = [ 0.00354, 0.00420, 0.00459, 0.00531, 0.00743, 0.01342 ]
5649 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
5651 keyname = "%s:%s"%(key, name)
5652 texname = "%s:%s"%(mat.getName(), keyname)
5653 value = luxProp(mat, keyname, default)
5655 cauchybusepreset = luxProp(mat, keyname+".cauchybusepreset", "true")
5656 luxBool("cauchybusepreset", cauchybusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
5658 if(cauchybusepreset.get() == "true"):
5659 cauchybpreset = luxProp(mat, keyname+".cauchybpreset", "01 - Fused silica glass")
5660 luxOption("cauchybpreset", cauchybpreset, cauchybnames, " PRESET", "select CauchyB preset", gui, 1.6)
5661 idx = cauchybnames.index(cauchybpreset.get())
5662 value.set(cauchybvals[idx])
5663 link = luxFloat(name, value, min, max, "cauchyb", hint, None, 1.6)
5665 link = luxFloat(name, value, min, max, "cauchyb", hint, gui, 1.6, 1)
5667 tex = luxProp(mat, keyname+".textured", False)
5668 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)]))
5669 if tex.get()=="true":
5670 if gui: gui.newline("", -2)
5671 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
5672 if value.get() != 1.0:
5673 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
5674 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
5677 def luxScaleUnits(keyname, default, mat, width=0.5, gui=None):
5678 # Length units widget for bumps, absorption and such.
5679 # @default can be passed as unit str or scale float
5680 units = ['m', 'cm', 'mm', 'cm^-1']
5681 scales = [1, 0.01, 0.001, 100]
5682 if type(default) is not str:
5683 try: default = units[scales.index(default)]
5684 except ValueError: default = 'm'
5685 scaleunits = luxProp(mat, keyname+'.scaleunits', default)
5686 luxOption('scaleunits', scaleunits, units, ' LENGTH UNITS', 'Select units from the list', gui, width)
5687 return scales[units.index(scaleunits.get())]
5689 def listNamedVolumes():
5690 # returns a dict of volumeName:volumeId pairs
5691 scn = Scene.GetCurrent()
5693 s = 'named_volumes:'
5695 for k, v in scn.properties['luxblend'].convert_to_pyobject().items():
5696 if k.startswith(s) and k[k.find('.')+1:] == 'name':
5697 d[v] = int(k[len(s):k.find('.')])
5700 if not d.has_key('0'):
5702 luxProp(scn, 'named_volumes:0.id', 0).set(0)
5703 luxProp(scn, 'named_volumes:0.name', '').set('world *')
5706 def getNamedVolume(id, scene=None, filter=[]):
5707 # returns a dict of volume properties' name:value pairs
5709 scn = Scene.GetCurrent()
5713 s = 'named_volumes:%s.' % id
5714 for k, v in scn.properties['luxblend'].convert_to_pyobject().items():
5716 if k[:7] == '__hash:':
5717 (kn, vl) = v.split(' = ')
5718 if kn[:len(s)] == s:
5721 if scene is None: return None
5723 d['name'] = 'world *'
5728 except KeyError: pass
5731 def luxNamedVolume(mat, volume_prop, gui=None):
5732 # Possible values for volume_prop: 'Exterior', 'Interior'
5734 # References to each volume are stored in two places. First, in regular
5735 # material in ${volume_prop}_vol_id Lux property which has an int index of
5736 # the volume assigned to this mat. Second, volume and its texture proper-
5737 # ties are stored in global scene properties "named_volumes" namespace
5738 # in the form "namespace:volumeId.volumeProperty". We use ids instead of
5739 # plane names to facilitate volume renaming.
5740 volumes = listNamedVolumes()
5741 if gui: gui.newline('Medium name:', 0, 0, None, [0.4,0.4,0.6])
5742 volumeId = luxProp(mat, '%s_vol_id' % (volume_prop), 0)
5743 volumeName = luxProp(mat, '%s_vol_name' % (volume_prop), '')
5744 volumeUID = luxProp(mat, '%s_vol_guid' % (volume_prop), '')
5745 unmutable = True if volumeId.get() == 0 else False
5746 # link volume data to the scene UID if it's not linked already
5747 if not volumeUID.get():
5748 volumeUID.set(luxUID)
5749 # is that a native volume data or maybe we linked material
5750 # from another scene? lets see and import if necessary
5751 elif volumeUID.get() != luxUID:
5752 print 'Global properties for medium "%s" are supposedly linked' % volumeName.get(), "\nfrom another scene. Attempting to import..."
5753 imported = importNamedVolume(volumeId, volumeName, volumeUID)
5754 if imported is True:
5755 print 'Medium properties imported successfully', "\n"
5756 # reloading volumes data
5757 volumes = listNamedVolumes()
5758 volumeId = luxProp(mat, '%s_vol_id' % (volume_prop), 0)
5759 volumeName = luxProp(mat, '%s_vol_name' % (volume_prop), '')
5760 elif imported is False:
5761 print 'Medium properties not found in the linked scenes. Import failed', "\n"
5763 print 'Medium properties import is unnecessary', "\n"
5764 # do we have that volume in the scene data?
5765 if not volumes.has_key(volumeName.get()):
5766 # seems selected volume was renamed or deleted.
5767 # lets try to update its name from id (if it still exists)
5769 volumeName.set(volumes.keys()[volumes.values().index(volumeId.get())])
5772 Blender.Window.QRedrawAll()
5773 luxOption('%s_vol_name'%(volume_prop), volumeName, volumes.keys(), ' AVAILABLE MEDIUMS', 'Select medium from the list', gui, 1.1 if not unmutable else 1.5)
5775 if volumeName.get(): volumeId.set(volumes[volumeName.get()])
5776 else: volumeId.set(0) # no volume was selected yet for that property
5781 r = gui.getRect(0.2, 1)
5782 Draw.Button('X', evtLuxGui, r[0], r[1], r[2], r[3], 'Delete a link to this medium', lambda e,v: showVolumesMenu(mat,volume_prop,4))
5783 luxBool('%s_vol_fixed' % (volume_prop), luxProp(Scene.GetCurrent(), 'named_volumes:%s.fixed' % volumeId.get(), 'false'), 'F', 'Saves this medium even if it has no users', gui, 0.2)
5784 r = gui.getRect(0.5, 1)
5785 Draw.Button('Options', evtLuxGui, r[0], r[1], r[2], r[3], 'Manage mediums', lambda e,v: showVolumesMenu(mat,volume_prop))
5787 volId = volumeId.get()
5789 luxNamedVolumeTexture(volId, gui)
5791 gui.newline(); r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
5792 Draw.Text("use Cam/Env tab to configure world medium")
5794 return "\n\t%s \"%s\"" % (volume_prop, getNamedVolume(volId)['name'])
5796 def luxNamedVolumeTexture(volId, gui=None):
5798 return (t1[0]+t2[0], t1[1]+t2[1])
5799 scn = Scene.GetCurrent()
5800 keyname = 'named_volumes:%s.' % volId
5802 volume_types = ['clear']
5803 volume_type = luxProp(scn, keyname+'type', volume_types[0])
5804 if gui: gui.newline('type:', 0, 0)
5805 luxOption(keyname+'type', volume_type, volume_types, ' MEDIUM TYPES', 'Select medium type from the list', gui, 2.0)
5806 volType = '"%s"' % volume_type.get()
5808 if volume_type.get() == 'clear':
5809 usecolor = luxProp(scn, keyname+'usecolor', 'true')
5810 usedepth = luxProp(scn, keyname+'usedepth', 'true')
5811 (s, l) = c((s, l), luxTexture('value', keyname+'tex', 'fresnel', 1.459 if volId != 0 else 1.0002926, 1.0, 6.0, 'IOR', 'ior', scn, gui, 0, 1))
5812 (s1, l1) = luxSpectrumTexture('absorption', keyname+'absorption', '1.0 1.0 1.0', 1.0 if usedepth.get() == 'true' else 1000.0, 'absorption:', '', scn, gui, 1)
5813 absorb_tex = luxProp(scn, keyname+'absorption:absorption.textured', 'false')
5814 if usedepth.get() == 'true' and absorb_tex.get() != 'true':
5815 luxBool('usecolor', usecolor, 'Color', 'Resulting light color at given depth of the medium', gui, 0.5)
5816 if absorb_tex.get() != 'true':
5817 luxBool('usedepth', usedepth, 'at depth' if usedepth.get() == 'true' else 'Color at depth', 'Resulting light color at given depth of the medium' if usecolor.get() == 'true' else 'Amount of light absorbed at given depth of the medium', gui, 0.5 if usedepth.get() == 'true' else 1.0)
5818 if usedepth.get() == 'true' and absorb_tex.get() != 'true':
5819 texkey = 'named_volumes:%s.absorption:absorption' % volId
5820 usetex = luxProp(scn, texkey+'.textured', None)
5821 depth = luxProp(scn, keyname+'depth', 1.0)
5822 luxFloat('depth', depth, 0.001, 1000.0, 'depth', 'Depth of the fixed point inside the medium', gui, 0.5)
5823 scale = luxScaleUnits(keyname+'scale', 'm', scn, 0.5, gui)
5824 if usecolor.get() == 'true':
5825 factor = lambda rgb: [ (-math.log(max([rg(float(i)),1e-30]))/(depth.get()*scale)) * (rg(float(i))==1.0 and -1 or 1) for i in rgb ]
5827 factor = lambda rgb: [ rg(float(i)) * (1/(depth.get()*scale)) for i in rgb ]
5828 if l1[l1.find('"')+1:].startswith('color'):
5829 rgb = factor(l1[l1.find('[')+1:l1.rfind(']')].split(' '))
5830 l1 = l1[:l1.find('[')] + '[%s %s %s]' % (rgb[0], rgb[1], rgb[2])
5831 elif usetex.get() == 'true':
5832 tex = s1.split("\n")
5834 if t.startswith('Texture "Scene:%s.scale"' % texkey):
5835 rgb = factor(t[t.rfind('[')+1:t.rfind(']')].split(' '))
5836 tex[tex.index(t)] = t[:t.rfind('[')] + '[%s %s %s]' % (rgb[0], rgb[1], rgb[2])
5838 (s, l) = c((s, l), (s1, l1))
5842 importedVolumeIdsTranslation = {}
5843 def importNamedVolume(volumeId, volumeName, volumeUID):
5844 # scans all linked libraries and imports volume
5845 # data from another scene object if possible.
5846 def assignName(name, names):
5847 # helper function to set a proper name for imported
5848 # object without overwriting existing ones
5849 if not name in names:
5852 if not (name[-4] == '.' and name[-3:].isdigit): subname = name
5853 else: subname = name[:-4]
5854 for i in range(1, 1000):
5855 newname = subname+'.'+str(i).rjust(3, '0')
5856 if not newname in names: return newname
5857 def importFromScene(scn, linkedScn, volumeId, volumeName, volumeUID):
5858 # helper function to scan a passed scene object for
5859 # matching uid and volume properties data and import
5860 # them in the active scene if found
5861 global importedVolumeIdsTranslation
5863 linkedUID = luxProp(linkedScn, 'UID', '')
5864 if volumeUID.get() == linkedUID.get():
5865 print ' scene UID matched, loading mediums data'
5866 linkedVolumeData = getNamedVolume(volumeId.get(), linkedScn)
5867 currentVolumeData = getNamedVolume(volumeId.get(), scn)
5868 linkedDataFiltered = getNamedVolume(volumeId.get(), linkedScn, filter=['id', 'name'])
5869 print ' - target medium found: ID %s, name "%s"' % (linkedVolumeData['id'], linkedVolumeData['name'])
5870 if linkedVolumeData != currentVolumeData and linkedVolumeData is not None:
5871 volumes = listNamedVolumes()
5872 newId = max(volumes.values())+1
5873 prefix = 'named_volumes:%s.' % newId
5874 importedVolumeIdsTranslation[linkedVolumeData['id']] = newId
5876 i = [ getNamedVolume(vol, filter=['id', 'name']) for vol in volumes.values() ].index(linkedDataFiltered)
5877 print ' properties are the same, updating ID'
5878 volumeId.set(volumes.values()[i])
5882 print ' importing medium global properties'
5883 for k, v in linkedVolumeData.items():
5885 volumeId.set(newId) # material property
5887 newName = assignName(v, volumes.keys())
5888 volumeName.set(newName) # material property
5889 luxProp(scn, prefix+k, '').set(newName)
5891 luxProp(scn, prefix+k, '').set(v)
5892 print ' medium properties imported under name "%s"' % newName
5895 print ' properties are the same or empty, skipping import'
5898 print ' scene UID mismatch, skipping'
5902 Library = Blender.Library
5903 scn = Scene.GetCurrent()
5904 allscenes = Scene.Get()
5905 linkedLibs = Library.LinkedLibs()
5906 print ' - active scene "%s" UID %s' % (scn.name, luxUID)
5907 print ' - searching for scene UID', volumeUID.get()
5909 print ' - searching in linked libraries'
5910 for lib in linkedLibs:
5911 print ' - opening Blender library path', sys.expandpath(lib)
5913 Library.Open(sys.expandpath(lib))
5915 print ' error opening library file, skipping'
5917 for scnName in Library.Datablocks('Scene'):
5918 print ' - loading library scene "%s"' % scnName
5919 Library.Load(scnName, 'Scene', 0)
5920 # we aren't getting a scene obj explicitly by name because after linking we'll
5921 # likely end up with two or more scenes with the same name, thus Blender will
5922 # return the first one which is the active scene
5923 for i, s in enumerate(Scene.Get()):
5924 # we cannot use 's in allscenes' directly as objects will be
5925 # compared by their str representations and not hashes in that case
5926 if not True in [ s == a for a in allscenes ]:
5927 linkedScn = Scene.Get()[i] ; break
5928 imported = importFromScene(scn, linkedScn, volumeId, volumeName, volumeUID)
5929 print ' - unlinking library scene "%s"' % scnName
5930 for obj in linkedScn.objects: linkedScn.objects.unlink(obj)
5931 Scene.Unlink(linkedScn)
5933 print ' - closing library path', sys.expandpath(lib)
5936 if imported is False and len(allscenes) > 1:
5937 print ' - searching in the current blend-file scenes'
5938 for linkedScn in allscenes:
5939 if linkedScn != scn:
5940 print ' - looking in scene "%s"' % linkedScn.name
5941 imported = importFromScene(scn, linkedScn, volumeId, volumeName, volumeUID)
5943 volumeUID.set(luxUID) # material property
5946 def gcNamedVolumes(scn, gui=True):
5947 # garbage collector for named volumes
5949 mats = Material.Get()
5950 vols = listNamedVolumes()
5951 # searching volumes directly linked from materials
5953 for volume_prop in ['Exterior', 'Interior']:
5954 if luxProp(mat, '%s_vol_used' % (volume_prop), 'false').get() == 'true':
5955 used.add(luxProp(mat, '%s_vol_id' % (volume_prop), 0).get())
5956 # searching fixed volumes, protected from gc
5957 for vol in vols.values():
5958 if luxProp(scn, 'named_volumes:%s.fixed' % vol, 'false').get() == 'true':
5960 # cleaning unused after asking a user
5961 unused = set(vols.values()).difference(used)
5964 data = getNamedVolume(vol)
5965 if gui: r = Draw.PupMenu(' LuxRender medium "' + data['name'] + '" is currently unused:%t|Delete medium%x1|Keep medium%x2')
5966 if not gui or r == 1:
5967 for n in data.keys():
5968 luxProp(scn, 'named_volumes:%s.%s' % (vol,n), '').delete()
5969 print 'Unused medium "%s" removed from the scene' % data['name']
5970 Blender.Window.QRedrawAll()
5973 def luxLight(name, kn, mat, gui, level):
5975 if name != "": gui.newline(name+":", 10, level)
5976 else: gui.newline("color:", 0, level+1)
5977 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
5978 if gui: gui.newline("")
5979 link += luxFloat("power", luxProp(mat, kn+"light.power", 100.0), 0.0, 10000.0, "Power(W)", "AreaLight Power in Watts", gui)
5980 link += luxFloat("efficacy", luxProp(mat, kn+"light.efficacy", 17.0), 0.0, 100.0, "Efficacy(lm/W)", "Efficacy Luminous flux/watt", gui)
5981 if gui: gui.newline("")
5982 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
5983 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
5984 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 0.8)
5985 lg_disable = luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false")
5986 luxBool("lg_disable", lg_disable, "D", "Disable lightgroup during export", gui, 0.2)
5987 if lg_disable.get() == "true":
5990 if gui: gui.newline("Photometric")
5991 pm = luxProp(mat, kn+"light.usepm", "false")
5992 luxCollapse("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
5994 if(pm.get()=="true"):
5995 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
5996 pmtypes = ["IESna", "imagemap"]
5997 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
5998 if(pmtype.get() == "imagemap"):
5999 map = luxProp(mat, kn+"light.pmmapname", "")
6000 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
6001 if(pmtype.get() == "IESna"):
6002 map = luxProp(mat, kn+"light.pmiesname", "")
6003 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
6005 if gui: gui.newline("Hints")
6006 hints = luxProp(mat, kn+"light.usehints", "false")
6007 luxCollapse("hints", hints, "Rendering Hints", "Enable Rendering Hints options", gui, 2.0)
6009 if(hints.get()=="true"):
6010 link += luxFloat("importance", luxProp(mat, kn+"light.hints.importance", 1.0), 0.0, 100.0, "Importance", "User defined light importance for Light Strategies", gui, 2.0)
6012 has_bump_options = 0
6013 has_object_options = 1
6016 def luxLamp(name, kn, mat, gui, level):
6018 if name != "": gui.newline(name+":", 10, level)
6019 else: gui.newline("color:", 0, level+1)
6020 # if gui: gui.newline("", 10, level)
6021 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
6022 if gui: gui.newline("")
6023 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
6024 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
6025 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 0.8)
6026 lg_disable = luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false")
6027 luxBool("lg_disable", lg_disable, "D", "Disable lightgroup during export", gui, 0.2)
6029 if gui: gui.newline("Photometric")
6030 pm = luxProp(mat, kn+"light.usepm", "false")
6031 luxBool("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
6033 if(pm.get()=="true"):
6034 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
6035 pmtypes = ["IESna", "imagemap"]
6036 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
6037 if(pmtype.get() == "imagemap"):
6038 map = luxProp(mat, kn+"light.pmmapname", "")
6039 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
6040 if(pmtype.get() == "IESna"):
6041 map = luxProp(mat, kn+"light.pmiesname", "")
6042 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
6044 link += luxBool("flipz", luxProp(mat, kn+"light.flipZ", "true"), "Flip Z", "Flip Z direction in mapping", gui, 2.0)
6046 if gui: gui.newline("Hints")
6047 hints = luxProp(mat, kn+"light.usehints", "false")
6048 luxCollapse("hints", hints, "Rendering Hints", "Enable Rendering Hints options", gui, 2.0)
6050 if(hints.get()=="true"):
6051 link += luxFloat("importance", luxProp(mat, kn+"light.hints.importance", 1.0), 0.0, 100.0, "Importance", "User defined light importance for Light Strategies", gui, 2.0)
6055 def luxSpot(name, kn, mat, gui, level):
6057 if name != "": gui.newline(name+":", 10, level)
6058 else: gui.newline("color:", 0, level+1)
6059 # if gui: gui.newline("", 10, level)
6060 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
6061 if gui: gui.newline("")
6062 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
6063 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
6064 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 0.8)
6065 lg_disable = luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false")
6066 luxBool("lg_disable", lg_disable, "D", "Disable lightgroup during export", gui, 0.2)
6068 if gui: gui.newline("Projection")
6069 proj = luxProp(mat, kn+"light.usetexproj", "false")
6070 luxBool("projection", proj, "Texture Projection", "Enable imagemap texture projection", gui, 2.0)
6072 if(proj.get() == "true"):
6073 map = luxProp(mat, kn+"light.pmmapname", "")
6074 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 2.0)
6076 if gui: gui.newline("Hints")
6077 hints = luxProp(mat, kn+"light.usehints", "false")
6078 luxCollapse("hints", hints, "Rendering Hints", "Enable Rendering Hints options", gui, 2.0)
6080 if(hints.get()=="true"):
6081 link += luxFloat("importance", luxProp(mat, kn+"light.hints.importance", 1.0), 0.0, 100.0, "Importance", "User defined light importance for Light Strategies", gui, 2.0)
6086 def Preview_Sphereset(mat, kn, state):
6088 luxProp(mat, kn+"prev_sphere", "true").set("true")
6089 luxProp(mat, kn+"prev_plane", "false").set("false")
6090 luxProp(mat, kn+"prev_torus", "false").set("false")
6091 def Preview_Planeset(mat, kn, state):
6093 luxProp(mat, kn+"prev_sphere", "true").set("false")
6094 luxProp(mat, kn+"prev_plane", "false").set("true")
6095 luxProp(mat, kn+"prev_torus", "false").set("false")
6096 def Preview_Torusset(mat, kn, state):
6098 luxProp(mat, kn+"prev_sphere", "true").set("false")
6099 luxProp(mat, kn+"prev_plane", "false").set("false")
6100 luxProp(mat, kn+"prev_torus", "false").set("true")
6105 def Preview_Update(mat, kn, defLarge, defType, texName, name, level):
6106 #print("%s %s %s %s %s %s %s" % (mat, kn, defLarge, defType, texName, name, level))
6111 Blender.Window.WaitCursor(True)
6112 scn = Scene.GetCurrent()
6114 # set path mode to absolute for preview
6115 pm_prop = luxProp(scn, "pathmode", "absolute")
6117 pm_prop.set('absolute')
6120 # Size of preview thumbnail
6121 thumbres = 110 # default 110x110
6123 large = luxProp(mat, kn+"prev_large", "true")
6125 large = luxProp(mat, kn+"prev_large", "false")
6126 if(large.get() == "true"):
6127 thumbres = 140 # small 140x140
6129 thumbbuf = thumbres*thumbres*3
6131 # consolebin = luxProp(scn, "luxconsole", "").get()
6133 p = get_lux_pipe(scn, buf=thumbbuf, type="luxconsole")
6135 # Unremark to write debugging output to file
6136 # p.stdin = open('c:\preview.lxs', 'w')
6137 # p.stdin = open('/home/blender/renders/preview.lxs', 'w')
6140 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
6141 prev_plane = luxProp(mat, kn+"prev_plane", "false")
6142 prev_torus = luxProp(mat, kn+"prev_torus", "false")
6144 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
6145 prev_plane = luxProp(mat, kn+"prev_plane", "true")
6146 prev_torus = luxProp(mat, kn+"prev_torus", "false")
6148 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
6149 prev_plane = luxProp(mat, kn+"prev_plane", "false")
6150 prev_torus = luxProp(mat, kn+"prev_torus", "true")
6153 if prev_plane.get() != "true":
6154 if luxProp(mat, kn+"prev_zoom", "false").get() == "true":
6155 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')
6157 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')
6159 orientation = luxProp(mat, kn+"prev_orientation", "XY")
6160 if orientation.get() == "XY":
6161 p.stdin.write('LookAt 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0\n')
6162 elif orientation.get() == "XZ":
6163 p.stdin.write('LookAt 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0\n')
6165 p.stdin.write('LookAt 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0\n')
6166 if luxProp(mat, kn+"prev_zoom", "false").get() == "true":
6167 p.stdin.write('Camera "orthographic" "float screenwindow" [0.0 0.5 0.0 0.5]\n')
6169 p.stdin.write('Camera "orthographic" "float screenwindow" [-0.5 0.5 -0.5 0.5]\n')
6171 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))
6172 p.stdin.write('PixelFilter "mitchell" "float xwidth" [1.500000] "float ywidth" [1.500000] "float B" [0.333330] "float C" [0.333330] "bool supersample" ["true"]\n')
6174 scn = Scene.GetCurrent()
6175 defprevmat = luxProp(scn, "defprevmat", "high")
6176 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
6177 if quality.get()=="low":
6178 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [2]\n')
6179 elif quality.get()=="medium":
6180 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [4]\n')
6181 elif quality.get()=="high":
6182 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [8]\n')
6184 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [32]\n')
6186 if(prev_plane.get()=="false"):
6187 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')
6189 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')
6191 p.stdin.write('WorldBegin\n')
6192 if(prev_sphere.get()=="true"):
6193 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')
6194 elif (prev_plane.get()=="true"):
6197 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')
6198 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
6200 p.stdin.write('TransformBegin\n')
6201 p.stdin.write('Scale %f %f %f\n'%(obw,obw,obw))
6203 print("texture "+texName+" "+name)
6204 (str, link) = luxTexture(texName, name, "color", "1.0 1.0 1.0", None, None, "", "", mat, None, 0, level)
6205 link = link.replace(" "+texName+"\"", " Kd\"") # swap texture name to "Kd"
6206 p.stdin.write(str+"\n")
6207 p.stdin.write("Material \"matte\" "+link+"\n")
6210 for volume_prop in ['Exterior', 'Interior']:
6211 if luxProp(mat, '%s_vol_used'%(volume_prop), 'false').get() == 'true':
6212 volData = getNamedVolume(luxProp(mat, '%s_vol_id'%(volume_prop), 'false').get())
6213 volTex = luxNamedVolumeTexture(volData['id'])
6214 p.stdin.write("%s\nMakeNamedVolume \"%s\" %s\n" % (volTex[0], volData['name'], volTex[1]))
6216 p.stdin.write(luxMaterial(mat))
6217 link = luxProp(mat,"link","").get()
6218 if kn!="": link = link.rstrip("\"")+":"+kn.strip(".:")+"\""
6219 p.stdin.write(link+'\n')
6220 p.stdin.write('TransformEnd\n')
6222 if(prev_sphere.get()=="true"):
6223 p.stdin.write('Shape "sphere" "float radius" [1.0]\n')
6224 elif (prev_plane.get()=="true"):
6225 _points = "%(p)s %(p)s %(p)s %(p)s" % {'p': "%(x)s %(y)s %(z)s"} % \
6227 'x': '%.1f' if 'X' in orientation.get() else '0.0',
6228 'y': '%.1f' if 'Y' in orientation.get() else '0.0',
6229 'z': '%.1f' if 'Z' in orientation.get() else '0.0'
6230 } % (0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5)
6231 _uv = ' 0.0 1.0 0.0 0.0 1.0 0.0 1.0 1.0 ' if orientation.get() == 'XZ' else ' 1.0 1.0 1.0 0.0 0.0 0.0 0.0 1.0 '
6232 p.stdin.write('Shape "trianglemesh" "integer indices" [ 0 1 2 0 2 3 ] "point P" [%s] "float uv" [%s]\n' % (_points, _uv))
6233 elif (prev_torus.get()=="true"):
6234 p.stdin.write('Shape "torus" "float radius" [1.0]\n')
6235 p.stdin.write('AttributeEnd\n')
6236 # Checkerboard floor
6237 if(prev_plane.get()=="false"):
6238 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')
6239 p.stdin.write('Texture "checks::pattern" "float" "checkerboard"')
6240 p.stdin.write('"integer dimension" [2] "string aamode" ["supersample"]')
6241 p.stdin.write('"string mapping" ["uv"] "float uscale" [36.8] "float vscale" [36.0]\n')
6242 p.stdin.write('Texture "checks" "color" "mix" "texture amount" ["checks::pattern"] "color tex1" [0.9 0.9 0.9] "color tex2" [0.0 0.0 0.0]\n')
6243 p.stdin.write('Material "matte" "texture Kd" ["checks"]\n')
6244 p.stdin.write('Shape "loopsubdiv" "integer nlevels" [3] "bool dmnormalsmooth" ["true"] "bool dmsharpboundary" ["false"] ')
6245 p.stdin.write('"integer indices" [ 0 1 2 0 2 3 1 0 4 1 4 5 5 4 6 5 6 7 ]')
6246 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')
6247 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')
6248 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')
6249 p.stdin.write('AttributeEnd\n')
6251 area = luxProp(mat, kn+"prev_arealight", "false")
6252 if(prev_plane.get()=="false"):
6253 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')
6255 _area = area.get() ; area.set('false')
6256 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')
6257 _m = Mathutils.TranslationMatrix(Mathutils.Vector(0.5,0.5,3.5 if area.get() == "false" else 6.0))*Mathutils.RotationMatrix({'XY':0,'XZ':-90,'YZ':90}[orientation.get()],4,'x' if orientation.get() == "XZ" else 'y')
6258 _s = ' '.join(['%.5f' % b for a in _m for b in a])
6259 p.stdin.write('AttributeBegin\nTransform [%s]\n'%_s)
6260 if(area.get() == "false"):
6261 p.stdin.write('Texture "pL" "color" "blackbody" "float temperature" [6500.0]\n')
6262 p.stdin.write('LightSource "point" "texture L" ["pL"] "float gain" [0.002]')
6264 p.stdin.write('ReverseOrientation\n')
6265 p.stdin.write('AreaLightSource "area" "color L" [1.0 1.0 1.0]\n')
6266 if(prev_plane.get()=="false"):
6267 p.stdin.write(' "float gain" [0.3]\n')
6268 p.stdin.write('Shape "disk" "float radius" [1.0]\nAttributeEnd\n')
6269 if prev_plane.get() == 'true':
6271 p.stdin.write('WorldEnd\n')
6275 data = p.communicate()[0]
6282 if(datalen < thumbbuf):
6283 print("error on preview: got %i bytes, expected %i" % (datalen, thumbbuf))
6287 image.decodeLuxConsole(thumbres, thumbres, data)
6288 previewCache[(mat.name+":"+kn).__hash__()] = image
6290 Blender.Window.WaitCursor(False)
6292 def luxPreview(mat, name, defType=0, defEnabled=False, defLarge=False, texName=None, gui=None, level=0, color=None):
6296 if texName: kn += ":"+texName
6297 if kn != "": kn += "."
6298 if(defEnabled == True):
6299 showpreview = luxProp(mat, kn+"prev_show", "true")
6301 showpreview = luxProp(mat, kn+"prev_show", "false")
6302 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)]))
6303 if showpreview.get()=="true":
6305 large = luxProp(mat, kn+"prev_large", "true")
6307 large = luxProp(mat, kn+"prev_large", "false")
6310 if(large.get() == "true"):
6314 r = gui.getRect(1.1, rr)
6316 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)
6317 try: previewCache[(mat.name+":"+kn).__hash__()].draw(r[0]-82, r[1]+4)
6320 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
6321 prev_plane = luxProp(mat, kn+"prev_plane", "false")
6322 prev_torus = luxProp(mat, kn+"prev_torus", "false")
6324 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
6325 prev_plane = luxProp(mat, kn+"prev_plane", "true")
6326 prev_torus = luxProp(mat, kn+"prev_torus", "false")
6328 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
6329 prev_plane = luxProp(mat, kn+"prev_plane", "false")
6330 prev_torus = luxProp(mat, kn+"prev_torus", "true")
6332 # preview mode toggle buttons
6333 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)]))
6334 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)]))
6335 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)]))
6338 zoom = luxProp(mat, kn+"prev_zoom", "false")
6339 Draw.Toggle("Zoom", evtLuxGui, r[0]+66, r[1]+100+voffset, 62, 18, zoom.get()=="true", "Zoom in to preview object", lambda e,v: zoom.set(["false","true"][bool(v)]))
6341 area = luxProp(mat, kn+"prev_arealight", "false")
6342 if not prev_plane.get()=="true":
6343 Draw.Toggle("Area", evtLuxGui, r[0]+133, r[1]+100+voffset, 62, 18, area.get()=="true", "Use area lightsource instead of point light", lambda e,v: area.set(["false","true"][bool(v)]))
6346 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
6347 Draw.Number("Width:", evtLuxGui, r[0]+66, r[1]+78+voffset, 129, 18, float(obwidth.get()), 0.001, 10, "The width of the preview object in Blender/LuxRender 1m units", lambda e,v: obwidth.set(v))
6349 # Orientation controls for plane obj
6350 if prev_plane.get() == "true":
6351 orientation = luxProp(mat, kn+"prev_orientation", "XY")
6352 Draw.Toggle("XY", evtLuxGui, r[0]+66, r[1]+56+voffset, 41, 18, orientation.get()=="XY", "Position plane over XY axes ('top' view)", lambda e,v: orientation.set("XY"))
6353 Draw.Toggle("XZ", evtLuxGui, r[0]+110, r[1]+56+voffset, 41, 18, orientation.get()=="XZ", "Position plane over XZ axes ('front' view)", lambda e,v: orientation.set("XZ"))
6354 Draw.Toggle("YZ", evtLuxGui, r[0]+154, r[1]+56+voffset, 41, 18, orientation.get()=="YZ", "Position plane over YZ axes ('side' view)", lambda e,v: orientation.set("YZ"))
6357 Draw.Toggle("Large", evtLuxGui, r[0]+200, r[1]+78+voffset, 88, 18, large.get()=="true", "Show larger preview image", lambda e,v: large.set(["false","true"][bool(v)]))
6360 qs = ["low","medium","high","very high"]
6361 scn = Scene.GetCurrent()
6362 defprevmat = luxProp(scn, "defprevmat", "high")
6363 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
6364 luxOptionRect("quality", quality, qs, " Quality", "Select preview quality (higher quality > less noise > longer update)", gui, r[0]+200, r[1]+100+voffset, 88, 18)
6367 Draw.Button("Update Preview", evtLuxGui, r[0]+133, r[1]+5, 154, 18, "Update Material Preview", lambda e,v: Preview_Update(mat, kn, defLarge, defType, texName, name, level))
6369 # Reset depths after getRect()
6374 def luxMaterialBlock(name, luxname, key, mat, gui=None, level=0, str_opt=""):
6375 global icon_mat, icon_matmix, icon_map3dparam
6377 return (t1[0]+t2[0], t1[1]+t2[1])
6379 if key == "": keyname = kn = name
6380 else: keyname = kn = "%s:%s"%(key, name)
6381 if kn != "": kn += "."
6382 if keyname == "": matname = mat.getName()
6383 else: matname = "%s:%s"%(mat.getName(), keyname)
6386 mattype = luxProp(mat, kn+"type", "matte")
6387 # Set backwards compatibility of glossy material from plastic and substrate
6388 if(mattype.get() == "substrate" or mattype.get() == "plastic"):
6389 mattype.set("glossy")
6391 # this is reverse order than in shown in the dropdown list
6392 materials = ["null","mix","mirror","shinymetal","metal","mattetranslucent","matte","glossy_lossy","glossy","roughglass","glass","glass2","carpaint"]
6394 if level == 0: materials = ["portal", "light", "boundvolume"]+materials
6397 if mattype.get() == "mix": icon = icon_matmix
6398 if level == 0: gui.newline("Material type:", 12, level, icon, [0.75,0.5,0.25])
6399 else: gui.newline(name+":", 12, level, icon, scalelist([0.75,0.6,0.25],2.0/(level+2)))
6402 link = luxOption("type", mattype, materials, " TYPE", "select material type", gui)
6403 showadvanced = luxProp(mat, kn+"showadvanced", "false")
6404 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
6405 showhelp = luxProp(mat, kn+"showhelp", "false")
6406 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
6408 # show copy/paste menu button
6409 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))
6411 # Draw Material preview option
6415 if gui: luxPreview(mat, keyname, 0, showmatprev, True, None, gui, level, [0.746, 0.625, 0.5])
6418 if gui: gui.newline()
6419 has_object_options = 0 # disable object options by default
6420 has_volume_options = 0 # disable named volume options by default
6421 has_bump_options = 0 # disable bump mapping options by default
6422 has_emission_options = 0 # disable emission options by default
6423 has_compositing_options = 0 # disable compositing options by default
6425 if mattype.get() == "mix":
6426 (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))
6428 r = gui.getRect(2, 1)
6429 Draw.Button("Flip material slots", evtLuxGui, r[0], r[1], r[2], r[3], "Flip mat1 and mat2 contents", lambda e,v: flipMixMat(mat,keyname))
6430 (str,link) = c((str,link), luxMaterialBlock("mat1", "namedmaterial1", keyname, mat, gui, level+1))
6431 (str,link) = c((str,link), luxMaterialBlock("mat2", "namedmaterial2", keyname, mat, gui, level+1))
6432 has_volume_options = 1
6433 has_bump_options = 0
6434 has_object_options = 1
6435 has_emission_options = 1
6436 has_compositing_options = 0
6438 if mattype.get() == "light":
6439 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
6440 if luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false").get() == "true":
6441 # pass dummy mat instead of light material if lightgroup is disabled
6442 link = "Material \"matte\" # dummy material\n"
6444 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
6445 link = "LightGroup \"%s\"\n"%lightgroup.get()
6448 link += "AreaLightSource \"area\""
6449 (str,link) = c((str,link), luxLight("", kn, mat, gui, level))
6450 has_volume_options = 1
6451 has_bump_options = 0
6452 has_object_options = 1
6453 has_emission_options = 0
6454 has_compositing_options = 1
6456 if mattype.get() == "boundvolume":
6458 voltype = luxProp(mat, kn+"vol.type", "homogeneous")
6459 vols = ["homogeneous", "exponential", "cloud"]
6460 vollink = luxOption("type", voltype, vols, "type", "", gui)
6461 if voltype.get() == "homogeneous":
6462 link = "Volume \"homogeneous\""
6463 if voltype.get() == "exponential":
6464 link = "Volume \"exponential\""
6465 if voltype.get() == "cloud":
6466 link = "Volume \"cloud\""
6468 if gui: gui.newline("absorption:", 0, level+1)
6469 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)
6470 if gui: gui.newline("scattering:", 0, level+1)
6471 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)
6472 if gui: gui.newline("emission:", 0, level+1)
6473 link += luxRGB("Le", luxProp(mat, kn+"vol.le", "0.0 0.0 0.0"), 1.0, "Le", "The volume's emission spectrum", gui)
6474 if gui: gui.newline("assymetry:", 0, level+1)
6475 link += luxFloat("g", luxProp(mat, kn+"vol.g", 0.0), 0.0, 100.0, "g", "The phase function asymmetry parameter", gui)
6477 if voltype.get() == "exponential":
6478 if gui: gui.newline("form:", 0, level+1)
6479 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)
6480 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)
6481 if gui: gui.newline("updir:", 0, level+1)
6482 link += luxVector("updir", luxProp(mat, kn+"vol.updir", "0 0 1"), -1.0, 1.0, "updir", "Up direction vector", gui, 2.0)
6484 if voltype.get() == "cloud":
6485 if gui: gui.newline("cloud:", 0, level+1)
6486 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)
6487 link += luxFloat("noisescale", luxProp(mat, kn+"vol.noisescale", 0.3), 0.1, 2.0, "noisesize", "Size of cloud noise", gui)
6488 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)
6489 link += luxFloat("noiseoffset", luxProp(mat, kn+"vol.noiseoffset", 0.0), 0.0, 1000.0, "noiseoffset", "Useful for creating unique clouds", gui )
6490 link += luxInt("octaves", luxProp(mat, kn+"vol.octaves", 3), 1, 8, "octaves", "Sets the amount of detail for the noise", gui )
6491 link += luxFloat("omega", luxProp(mat, kn+"vol.omega", 0.75), 0.1, 1.0, "omega", "Sets the scale difference of each successive octave", gui )
6492 link += luxFloat("sharpness", luxProp(mat, kn+"vol.sharpness", 6.0), 0.2, 10.0, "sharpness", "Sets the sharpness of the noise", gui)
6493 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)
6494 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)
6495 link += luxInt("spheres", luxProp(mat, kn+"vol.spheres", 2000), 0, 10000, "spheres", "Number of small spheres for cumulus shape. 0 is non-cumulus.", gui )
6496 link += luxFloat("spheresize", luxProp(mat, kn+"vol.spheresize", 0.15), 0.05, 0.55, "spheresize", "Size of cumulus spheres", gui)
6500 has_bump_options = 0
6501 has_object_options = 0
6502 has_emission_options = 0
6506 if mattype.get() == "carpaint":
6507 carpaintData = { # Kd RGB Ks1 RGB Ks2 RGB Ks3 RGB R1 R2 R3 M1 M2 M3
6508 "ford f8": [ [0.0012, 0.0015, 0.0018], [0.0049, 0.0076, 0.0120], [0.0100, 0.0130, 0.0180], [0.0070, 0.0065, 0.0077], 0.1500, 0.0870, 0.9000, 0.3200, 0.1100, 0.0130 ],
6509 "polaris silber": [ [0.0550, 0.0630, 0.0710], [0.0650, 0.0820, 0.0880], [0.1100, 0.1100, 0.1300], [0.0080, 0.0130, 0.0150], 1.0000, 0.9200, 0.9000, 0.3800, 0.1700, 0.0130 ],
6510 "opel titan": [ [0.0110, 0.0130, 0.0150], [0.0570, 0.0660, 0.0780], [0.1100, 0.1200, 0.1300], [0.0095, 0.0140, 0.0160], 0.8500, 0.8600, 0.9000, 0.3800, 0.1700, 0.0140 ],
6511 "bmw339": [ [0.0120, 0.0150, 0.0160], [0.0620, 0.0760, 0.0800], [0.1100, 0.1200, 0.1200], [0.0083, 0.0150, 0.0160], 0.9200, 0.8700, 0.9000, 0.3900, 0.1700, 0.0130 ],
6512 "2k acrylack": [ [0.4200, 0.3200, 0.1000], [0.0000, 0.0000, 0.0000], [0.0280, 0.0260, 0.0060], [0.0170, 0.0075, 0.0041], 1.0000, 0.9000, 0.1700, 0.8800, 0.8000, 0.0150 ],
6513 "white": [ [0.6100, 0.6300, 0.5500], [2.6e-6, 3.1e-4, 3.1e-8], [0.0130, 0.0110, 0.0083], [0.0490, 0.0420, 0.0370], 0.0490, 0.4500, 0.1700, 1.0000, 0.1500, 0.0150 ],
6514 "blue": [ [0.0079, 0.0230, 0.1000], [0.0011, 0.0015, 0.0019], [0.0250, 0.0300, 0.0430], [0.0590, 0.0740, 0.0820], 1.0000, 0.0940, 0.1700, 0.1500, 0.0430, 0.0200 ],
6515 "blue matte": [ [0.0099, 0.0360, 0.1200], [0.0032, 0.0045, 0.0059], [0.1800, 0.2300, 0.2800], [0.0400, 0.0490, 0.0510], 1.0000, 0.0460, 0.1700, 0.1600, 0.0750, 0.0340 ]
6517 if gui: gui.newline("Preset:", 0, level+1)
6518 carname = luxProp(mat, kn+"carpaint.name", "Custom")
6519 cars = ["Custom","ford f8","polaris silber","opel titan","bmw339","2k acrylack","white","blue","blue matte"]
6520 carlink = luxOption("name", carname, cars, "name", "", gui)
6521 if carname.get() == "Custom":
6522 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
6523 (str,link) = c((str,link), luxSpectrumTexture("Ks1", keyname, "1.0 1.0 1.0", 1.0, "specular1", "", mat, gui, level+1))
6524 (str,link) = c((str,link), luxSpectrumTexture("Ks2", keyname, "1.0 1.0 1.0", 1.0, "specular2", "", mat, gui, level+1))
6525 (str,link) = c((str,link), luxSpectrumTexture("Ks3", keyname, "1.0 1.0 1.0", 1.0, "specular3", "", mat, gui, level+1))
6526 (str,link) = c((str,link), luxFloatTexture("R1", keyname, 1.0, 0.0, 1.0, "R1", "", mat, gui, level+1))
6527 (str,link) = c((str,link), luxFloatTexture("R2", keyname, 1.0, 0.0, 1.0, "R2", "", mat, gui, level+1))
6528 (str,link) = c((str,link), luxFloatTexture("R3", keyname, 1.0, 0.0, 1.0, "R3", "", mat, gui, level+1))
6529 (str,link) = c((str,link), luxFloatTexture("M1", keyname, 1.0, 0.0, 1.0, "M1", "", mat, gui, level+1))
6530 (str,link) = c((str,link), luxFloatTexture("M2", keyname, 1.0, 0.0, 1.0, "M2", "", mat, gui, level+1))
6531 (str,link) = c((str,link), luxFloatTexture("M3", keyname, 1.0, 0.0, 1.0, "M3", "", mat, gui, level+1))
6533 luxProp(mat, keyname+':Kd', '1.0 1.0 1.0').set(' '.join(map(__builtins__['str'], carpaintData[carname.get()][0])))
6534 luxProp(mat, keyname+':Ks1', '1.0 1.0 1.0').set(' '.join(map(__builtins__['str'], carpaintData[carname.get()][1])))
6535 luxProp(mat, keyname+':Ks2', '1.0 1.0 1.0').set(' '.join(map(__builtins__['str'], carpaintData[carname.get()][2])))
6536 luxProp(mat, keyname+':Ks3', '1.0 1.0 1.0').set(' '.join(map(__builtins__['str'], carpaintData[carname.get()][3])))
6537 luxProp(mat, keyname+':R1', 1.0).set(carpaintData[carname.get()][4])
6538 luxProp(mat, keyname+':R2', 1.0).set(carpaintData[carname.get()][5])
6539 luxProp(mat, keyname+':R3', 1.0).set(carpaintData[carname.get()][6])
6540 luxProp(mat, keyname+':M1', 1.0).set(carpaintData[carname.get()][7])
6541 luxProp(mat, keyname+':M2', 1.0).set(carpaintData[carname.get()][8])
6542 luxProp(mat, keyname+':M3', 1.0).set(carpaintData[carname.get()][9])
6544 absorption = luxProp(mat, keyname+".useabsorption", "false")
6545 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
6546 if absorption.get() == "true":
6547 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
6548 (str,link) = c((str,link), luxFloatTexture("d", keyname, 5.0, 0.0, 15.0, "depth", "", mat, gui, level+1))
6549 has_volume_options = 1
6550 has_bump_options = 1
6551 has_object_options = 1
6552 has_emission_options = 1
6553 has_compositing_options = 1
6555 if mattype.get() == "glass":
6556 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
6557 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
6558 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
6559 architectural = luxProp(mat, keyname+".architectural", "false")
6560 link += luxBool("architectural", architectural, "Architectural", "Enable architectural glass", gui, 2.0)
6561 if architectural.get() == "false":
6562 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
6563 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
6564 if chromadisp.get() == "true":
6565 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
6566 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
6567 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
6568 if thinfilm.get() == "true":
6569 (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))
6570 (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))
6571 has_volume_options = 1
6572 has_bump_options = 1
6573 has_object_options = 1
6574 has_emission_options = 1
6575 has_compositing_options = 1
6577 if mattype.get() == 'glass2':
6578 architectural = luxProp(mat, keyname+".architectural", "false")
6579 link += luxBool("architectural", architectural, "Architectural", "Enable architectural glass", gui, 2.0)
6580 if architectural.get() == "false":
6581 chromadisp = luxProp(mat, keyname+".dispersion", "false")
6582 link += luxBool("dispersion", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
6583 has_volume_options = 1
6584 has_bump_options = 1
6585 has_object_options = 1
6586 has_emission_options = 1
6587 has_compositing_options = 1
6589 if mattype.get() == "matte":
6590 orennayar = luxProp(mat, keyname+".orennayar", "false")
6591 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
6592 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
6593 if orennayar.get() == "true":
6594 (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))
6595 has_volume_options = 1
6596 has_bump_options = 1
6597 has_object_options = 1
6598 has_emission_options = 1
6599 has_compositing_options = 1
6601 if mattype.get() == "mattetranslucent":
6602 orennayar = luxProp(mat, keyname+".orennayar", "false")
6603 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
6604 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
6605 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
6606 if orennayar.get() == "true":
6607 (str,link) = c((str,link), luxFloatTexture("sigma", keyname, 0.0, 0.0, 100.0, "sigma", "", mat, gui, level+1))
6608 has_volume_options = 1
6609 has_bump_options = 1
6610 has_object_options = 1
6611 has_emission_options = 1
6612 has_compositing_options = 1
6614 if mattype.get() == "metal":
6615 if gui: gui.newline("name:", 0, level+1)
6616 metalname = luxProp(mat, kn+"metal.name", "")
6617 metalnames = ["aluminium","amorphous carbon","silver","gold","copper"]
6618 metals = [n for n in metalnames]
6620 if not(metalname.get() in metals):
6621 metals.append(metalname.get())
6622 metallink = luxOption("name", metalname, metals, "name", "", gui, 1.88)
6623 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"))
6624 link += luxstr(metallink)
6625 if not metalname.get() in metalnames:
6626 link = link.replace('"string name"', '"string filename"')
6627 anisotropic = luxProp(mat, kn+"metal.anisotropic", "false")
6630 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)]))
6631 if anisotropic.get()=="true":
6632 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
6633 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
6635 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
6636 (str,link) = c((str,link), (s, l))
6637 link += l.replace("uroughness", "vroughness", 1)
6638 has_volume_options = 1
6639 has_bump_options = 1
6640 has_object_options = 1
6641 has_emission_options = 1
6642 has_compositing_options = 1
6644 if mattype.get() == "mirror":
6645 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
6646 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
6647 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
6648 if thinfilm.get() == "true":
6649 (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))
6650 (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))
6651 has_volume_options = 1
6652 has_bump_options = 1
6653 has_object_options = 1
6654 has_emission_options = 1
6655 has_compositing_options = 1
6657 if mattype.get() == "roughglass":
6658 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
6659 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
6660 anisotropic = luxProp(mat, kn+"roughglass.anisotropic", "false")
6663 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)]))
6664 if anisotropic.get()=="true":
6665 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
6666 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
6668 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
6669 (str,link) = c((str,link), (s, l))
6670 link += l.replace("uroughness", "vroughness", 1)
6671 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
6672 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
6673 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
6674 if chromadisp.get() == "true":
6675 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
6676 has_volume_options = 1
6677 has_bump_options = 1
6678 has_object_options = 1
6679 has_emission_options = 1
6680 has_compositing_options = 1
6682 if mattype.get() == "shinymetal":
6683 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
6684 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
6685 anisotropic = luxProp(mat, kn+"shinymetal.anisotropic", "false")
6688 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)]))
6689 if anisotropic.get()=="true":
6690 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
6691 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
6693 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
6694 (str,link) = c((str,link), (s, l))
6695 link += l.replace("uroughness", "vroughness", 1)
6697 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
6698 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
6699 if thinfilm.get() == "true":
6700 (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))
6701 (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))
6702 has_volume_options = 1
6703 has_bump_options = 1
6704 has_object_options = 1
6705 has_emission_options = 1
6706 has_compositing_options = 1
6708 if mattype.get() in ("glossy", "glossy_lossy"):
6709 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
6710 useior = luxProp(mat, keyname+".useior", "false")
6713 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)]))
6714 if useior.get() == "true":
6715 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 50.0, "IOR", "", mat, gui, level+1))
6716 link += " \"color Ks\" [1.0 1.0 1.0]"
6718 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
6719 link += " \"float index\" [0.0]"
6720 anisotropic = luxProp(mat, kn+"glossy.anisotropic", "false")
6723 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)]))
6724 if anisotropic.get()=="true":
6725 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
6726 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
6728 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
6729 (str,link) = c((str,link), (s, l))
6730 link += l.replace("uroughness", "vroughness", 1)
6732 absorption = luxProp(mat, keyname+".useabsorption", "false")
6733 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
6734 if absorption.get() == "true":
6735 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
6736 (str,link) = c((str,link), luxFloatTexture("d", keyname, 0.15, 0.0, 15.0, "depth", "", mat, gui, level+1))
6737 has_volume_options = 1
6738 has_bump_options = 1
6739 has_object_options = 1
6740 has_emission_options = 1
6741 has_compositing_options = 1
6743 if mattype.get() == 'null':
6744 has_emission_options = 1
6746 # Bump mapping options (common)
6747 if (has_bump_options == 1):
6748 usebump = luxProp(mat, keyname+".usebump", "false")
6749 luxCollapse("usebump", usebump, "Bump Map", "Enable Bump Mapping options", gui, 2.0)
6750 if usebump.get() == "true":
6751 (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))
6753 # volume options (common)
6754 if has_volume_options == 1 and level == 0:
6755 for volume_prop in ['Exterior', 'Interior']:
6756 volume_used = luxProp(mat, '%s_vol_used'%(volume_prop), 'false')
6757 if gui: gui.newline('', 2, level, None, [0.4,0.4,0.6])
6758 luxCollapse('%s_vol_used'%(volume_prop), volume_used, "%s Medium"%(volume_prop), "%s medium settings"%(volume_prop), gui, 2.0)
6759 if volume_used.get() == "true":
6760 luxNamedVolume(mat, volume_prop, gui)
6762 # emission options (common)
6764 if (has_emission_options == 1):
6765 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
6766 useemission = luxProp(mat, "emission", "false")
6767 luxCollapse("useemission", useemission, "Emission", "Enable emission options", gui, 2.0)
6768 if useemission.get() == "true":
6769 # emission GUI is here but lux export will be done later
6770 luxLight("", "", mat, gui, level)
6771 else: luxProp(mat, "emission", "false").set("false") # prevent from exporting later
6774 # Compositing options (common)
6775 # Note - currently only display options when using distributedpath integrator
6776 integratortype = luxProp(Scene.GetCurrent(), "sintegrator.type", "bidirectional")
6777 if (integratortype.get() == "distributedpath" and level == 0):
6778 if (has_compositing_options == 1):
6779 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
6780 usecompo = luxProp(mat, "compo", "false")
6781 luxCollapse("compo", usecompo, "Compositing", "Enable Compositing options", gui, 2.0)
6782 if usecompo.get() == "true":
6783 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
6784 usecompoviz = luxProp(mat, "compo_viz", "false")
6785 luxCollapse("compo_viz", usecompoviz, "Visibility", "Enable Visibility Compositing options", gui, 2.0)
6786 if usecompoviz.get() == "true":
6787 if gui: gui.newline("View", 2, level, None, [0.35,0.35,0.55])
6788 compovizmat = luxProp(mat, "compo_viz_mat", "true")
6789 link += luxBool("compo_visible_material", compovizmat, "Material", "Enable View Visibility of Material", gui, 1.0)
6790 compovizemi = luxProp(mat, "compo_viz_emi", "true")
6791 link += luxBool("compo_visible_emission", compovizemi, "Emission", "Enable View Visibility of Emission", gui, 1.0)
6793 if gui: gui.newline("Indirect", 2, level, None, [0.35,0.35,0.55])
6794 compovizmati = luxProp(mat, "compo_viz_mati", "true")
6795 link += luxBool("compo_visible_indirect_material", compovizmati, "Material", "Enable InDirect Visibility of Material", gui, 1.0)
6796 compovizemii = luxProp(mat, "compo_viz_emii", "true")
6797 link += luxBool("compo_visible_indirect_emission", compovizemii, "Emission", "Enable InDirect Visibility of Emission", gui, 1.0)
6799 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
6800 overridealpha = luxProp(mat, "compo_o_alpha", "false")
6801 link += luxCollapse("compo_override_alpha", overridealpha, "Override Alpha", "Enable Manual control of alpha value", gui, 2.0)
6802 if overridealpha.get() == "true":
6803 if gui: gui.newline("Alpha", 2, level, None, [0.4,0.4,0.6])
6804 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)
6805 usecolorkey = luxProp(mat, "compo_usekey", "false")
6806 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
6807 link += luxCollapse("compo_use_key", usecolorkey, "Chroma Key", "Enable Chroma Object key", gui, 2.0)
6808 if usecolorkey.get() == "true":
6809 if gui: gui.newline("Key", 2, level, None, [0.35,0.35,0.55])
6810 link += luxRGB("compo_key_color", luxProp(mat, "compo_key_color", "0.0 0.0 1.0"), 1.0, "key", "", gui, 2.0)
6812 # transformation options (common)
6813 if (level == 0) and mattype.get() not in ['portal', 'null']:
6814 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
6815 usetransformation = luxProp(mat, "transformation", "false")
6816 luxCollapse("usetransformation", usetransformation, "Texture Transformation", "Enable transformation option", gui, 2.0)
6817 if usetransformation.get() == "true":
6818 scale = luxProp(mat, "3dscale", 1.0)
6819 rotate = luxProp(mat, "3drotate", "0 0 0")
6820 translate = luxProp(mat, "3dtranslate", "0 0 0")
6822 gui.newline("scale:", -2, level, icon_map3dparam)
6823 luxVectorUniform("scale", scale, 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
6824 gui.newline("rot:", -2, level, icon_map3dparam)
6825 luxVector("rotate", rotate, -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
6826 gui.newline("move:", -2, level, icon_map3dparam)
6827 luxVector("translate", translate, -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
6828 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"
6830 # Object options (common)
6831 if (level == 0) and (has_object_options == 1):
6832 if gui: gui.newline("Mesh:", 2, level, icon, [0.6,0.6,0.4])
6833 usesubdiv = luxProp(mat, "subdiv", "false")
6834 luxBool("usesubdiv", usesubdiv, "Subdivision", "Enable Loop Subdivision options", gui, 1.0)
6835 usedisp = luxProp(mat, "dispmap", "false")
6836 luxBool("usedisp", usedisp, "Displacement Map", "Enable Displacement mapping options", gui, 1.0)
6837 if usesubdiv.get() == "true" or usedisp.get() == "true":
6838 luxInt("sublevels", luxProp(mat, "sublevels", 2), 0, 12, "sublevels", "The number of levels of object subdivision", gui, 2.0)
6839 sharpbound = luxProp(mat, "sharpbound", "false")
6840 luxBool("sharpbound", sharpbound, "Sharpen Bounds", "Sharpen boundaries during subdivision", gui, 1.0)
6841 nsmooth = luxProp(mat, "nsmooth", "true")
6842 luxBool("nsmooth", nsmooth, "Smooth", "Smooth faces during subdivision", gui, 1.0)
6843 if usedisp.get() == "true":
6844 (str,ll) = c((str,link), luxDispFloatTexture("dispmap", keyname, 0.1, -10, 10.0, "dispmap", "Displacement Mapping amount", mat, gui, level+1))
6845 luxFloat("sdoffset", luxProp(mat, "sdoffset", 0.0), 0.0, 1.0, "Offset", "Offset for displacement map", gui, 2.0)
6846 usesubdiv.set("true")
6847 if gui: gui.newline('Hair:', 2, level, None, [0.6,0.6,0.4])
6848 luxFloat('hair_thickness', luxProp(mat, 'hair_thickness', 0.5), 0.001, 100.0, 'hair thickness', 'Hair strand diameter', gui, 1.5)
6849 luxScaleUnits('hair_thickness', 'mm', mat, 0.5, gui)
6851 if mattype.get() == "light":
6854 str += "MakeNamedMaterial \"%s\"%s\n"%(matname, link)
6855 return (str, " \"string %s\" [\"%s\"]"%(luxname, matname))
6858 def luxMaterial(mat, gui=None):
6861 if luxProp(mat, "type", "").get()=="": # lux material not defined yet
6862 print("Blender material \"%s\" has no LuxRender material definition, converting..."%(mat.getName()))
6864 convertMaterial(mat) # try converting the blender material to a lux material
6866 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
6867 if luxProp(mat, "type", "matte").get() != "light":
6868 link = "NamedMaterial \"%s\""%(mat.getName())
6870 for volume_prop in ['Exterior', 'Interior']:
6871 if luxProp(mat, '%s_vol_used'%(volume_prop), 'false').get() == 'true':
6872 link += luxNamedVolume(mat, volume_prop)
6873 # export emission options (no gui)
6874 useemission = luxProp(mat, "emission", "false")
6875 if useemission.get() == "true":
6876 lightgroup = luxProp(mat, "light.lightgroup", "default")
6877 if luxProp(Scene.GetCurrent(), "lightgroup.disable."+lightgroup.get(), "false").get() == "true":
6878 # skip export of emission component if lightgroup is disabled
6881 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
6882 link += "\n\tLightGroup \"%s\"\n"%lightgroup.get()
6884 (estr, elink) = luxLight("", "", mat, None, 0)
6886 link += "\n\tAreaLightSource \"area\" "+elink
6888 luxProp(mat, "link", "").set("".join(link))
6893 def luxVolume(mat, gui=None):
6896 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
6897 luxProp(mat, "link", "").set("".join(link))
6900 runRenderAfterExport = None
6901 def CBluxExport(default, run):
6902 global runRenderAfterExport
6903 runRenderAfterExport = run
6905 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
6906 if datadir=="": datadir = Blender.Get("datadir")
6908 if not os.path.exists(datadir):
6909 Draw.PupMenu("ERROR: output directory does not exist!")
6913 filename = datadir + os.sep + "default.lxs"
6914 save_still(filename)
6916 Window.FileSelector(save_still, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
6919 def CBluxAnimExport(default, run, fileselect=True):
6921 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
6922 if datadir=="": datadir = Blender.Get("datadir")
6924 if not os.path.exists(datadir):
6925 Draw.PupMenu("ERROR: output directory does not exist!")
6929 filename = datadir + os.sep + "default.lxs"
6933 Window.FileSelector(save_anim, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
6935 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
6936 if datadir=="": datadir = Blender.Get("datadir")
6937 filename = sys.makename(Blender.Get("filename") , ".lxs")
6941 # convert a Blender material to lux material
6942 def convertMaterial(mat):
6944 if str != "": return str+"."
6947 if str != "": return str+":"
6949 def mapConstDict(value, constant_dict, lux_dict, default=None):
6950 for k,v in constant_dict.items():
6951 if (v == value) and (lux_dict.has_key(k)):
6954 def getTexFlags(value, constant_dict):
6955 constant_dict = sorted(constant_dict, lambda x,y: cmp(y[1], x[1]))
6957 for f, v in constant_dict:
6962 flags_dict.append(f)
6965 def convertMapping(name, tex):
6966 if tex.texco == Texture.TexCo["UV"]:
6967 luxProp(mat, dot(name)+"mapping","").set("uv")
6968 luxProp(mat, dot(name)+"uscale", 1.0).set(tex.size[0])
6969 luxProp(mat, dot(name)+"vscale", 1.0).set(-tex.size[1])
6970 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5*(1.0-tex.size[0]))
6971 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]+1-(0.5*(1.0-tex.size[1])))
6972 if tex.mapping != Texture.Mappings["FLAT"]:
6973 print("Material Conversion Warning: for UV-texture-input only FLAT mapping is supported\n")
6975 if tex.mapping == Texture.Mappings["FLAT"]:
6976 luxProp(mat, dot(name)+"mapping","").set("planar") # make planar-mapping convert correctly from blender(WYSIWYG)- jens
6977 luxProp(mat, dot(name)+"v1", "1.0 1.0 1.0").setVector((0.5*tex.size[0], 0.0, 0.0))
6978 luxProp(mat, dot(name)+"v2", "0.0 0.0 0.0").setVector((0.0, -0.5*tex.size[1], -0.0))
6979 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5)
6980 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5)
6981 elif tex.mapping == Texture.Mappings["TUBE"]:
6982 luxProp(mat, dot(name)+"mapping","").set("cylindrical")
6983 elif tex.mapping == Texture.Mappings["SPHERE"]:
6984 luxProp(mat, dot(name)+"mapping","").set("spherical")
6985 else: luxProp(mat, dot(name)+"mapping","").set("planar")
6987 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]))
6988 luxProp(mat, dot(name)+"3dtranslate", "0.0 0.0 0.0").setVector((-tex.ofs[0], -tex.ofs[1], -tex.ofs[2]))
6990 def convertColorband(colorband):
6991 # colorbands are not supported in lux - so lets extract a average low-side and high-side color
6992 cb = [colorband[0]] + colorband[:] + [colorband[-1]]
6993 cb[0][4], cb[-1][4] = 0.0, 1.0
6994 low, high = [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]
6995 for i in range(1, len(cb)):
6997 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])
6998 high[c] += (cb[i-1][c]*cb[i-1][4] + cb[i][c]*cb[i][4]) * (cb[i][4]-cb[i-1][4])
7001 def createLuxTexture(name, tex):
7003 convertMapping(name, tex)
7004 if (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!=""):
7005 luxProp(mat, dot(name)+"texture", "").set("imagemap")
7006 luxProp(mat, dot(name)+"filename", "").set(texture.image.filename)
7007 luxProp(mat, dot(name)+"wrap", "").set(mapConstDict(texture.extend, Texture.ExtendModes, {"REPEAT":"repeat", "EXTEND":"clamp", "CLIP":"black"}, ""))
7009 if tex.texco != Texture.TexCo["GLOB"]:
7010 print("Material Conversion Warning: procedural textures supports global mapping only\n")
7011 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"}
7012 luxProp(mat, dot(name)+"bright", 1.0).set(texture.brightness)
7013 luxProp(mat, dot(name)+"contrast", 1.0).set(texture.contrast)
7014 if texture.type == Texture.Types["CLOUDS"]:
7015 luxProp(mat, dot(name)+"texture", "").set("blender_clouds")
7016 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"CLD_DEFAULT":"default", "CLD_COLOR":"color"}, ""))
7017 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
7018 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7019 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
7020 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7021 elif texture.type == Texture.Types["WOOD"]:
7022 luxProp(mat, dot(name)+"texture", "").set("blender_wood")
7023 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"WOD_BANDS":"bands", "WOD_RINGS":"rings", "WOD_BANDNOISE":"bandnoise", "WOD_RINGNOISE":"ringnoise"}, ""))
7024 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
7025 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7026 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
7027 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7028 luxProp(mat, dot(name)+"turbulence", 0.25).set(texture.turbulence)
7029 elif texture.type == Texture.Types["MUSGRAVE"]:
7030 luxProp(mat, dot(name)+"texture", "").set("blender_musgrave")
7031 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"}, ""))
7032 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7033 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7034 # 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)
7035 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
7036 else: luxProp(mat, dot(name)+"h", 1.0).set(0.5) # use a default value
7037 # bug in blender python API: values "offset" and "gain" are missing in Python-API (reported to Ideasman42 - will be fixed after Blender 2.47)
7039 luxProp(mat, dot(name)+"offset", 1.0).set(texture.offset)
7040 luxProp(mat, dot(name)+"gain", 1.0).set(texture.gain)
7041 except AttributeError: pass
7042 luxProp(mat, dot(name)+"lacu", 2.0).set(texture.lacunarity)
7043 luxProp(mat, dot(name)+"octs", 2.0).set(texture.octs)
7044 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
7045 elif texture.type == Texture.Types["MARBLE"]:
7046 luxProp(mat, dot(name)+"texture", "").set("blender_marble")
7047 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"MBL_SOFT":"soft", "MBL_SHARP":"sharp", "MBL_SHARPER":"sharper"}, ""))
7048 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
7049 luxProp(mat, dot(name)+"turbulence", 0.25).set(texture.turbulence)
7050 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
7051 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7052 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
7053 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7054 elif texture.type == Texture.Types["VORONOI"]:
7055 luxProp(mat, dot(name)+"texture", "").set("blender_voronoi")
7056 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])
7057 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
7058 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7059 luxProp(mat, dot(name)+"minkosky_exp", 2.5).set(texture.exp)
7060 luxProp(mat, dot(name)+"w1", 1.0).set(texture.weight1)
7061 luxProp(mat, dot(name)+"w2", 0.0).set(texture.weight2)
7062 luxProp(mat, dot(name)+"w3", 0.0).set(texture.weight3)
7063 luxProp(mat, dot(name)+"w4", 0.0).set(texture.weight4)
7064 elif texture.type == Texture.Types["NOISE"]:
7065 luxProp(mat, dot(name)+"texture", "").set("blender_noise")
7066 elif texture.type == Texture.Types["DISTNOISE"]:
7067 luxProp(mat, dot(name)+"texture", "").set("blender_distortednoise")
7068 luxProp(mat, dot(name)+"distamount", 1.0).set(texture.distAmnt)
7069 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7070 luxProp(mat, dot(name)+"type", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7071 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, noiseDict, ""))
7072 elif texture.type == Texture.Types["MAGIC"]:
7073 luxProp(mat, dot(name)+"texture", "").set("blender_magic")
7074 luxProp(mat, dot(name)+"turbulence", 0.25).set(texture.turbulence)
7075 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
7076 elif texture.type == Texture.Types["STUCCI"]:
7077 luxProp(mat, dot(name)+"texture", "").set("blender_stucci")
7078 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"STC_PLASTIC":"Plastic", "MSTC_WALLIN":"Wall In", "STC_WALLOUT":"Wall Out"}, ""))
7079 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
7080 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
7081 luxProp(mat, dot(name)+"turbulence", 0.25).set(texture.turbulence)
7082 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
7083 elif texture.type == Texture.Types["BLEND"]:
7084 luxProp(mat, dot(name)+"texture", "").set("blender_blend")
7085 luxProp(mat, dot(name)+"mtype", "").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"}, ""))
7086 luxProp(mat, dot(name)+"flag", "false").set(str('FLIPBLEND' in getTexFlags(texture.flags, Texture.Flags.items())).lower())
7088 print("Material Conversion Warning: SORRY, this procedural texture isn\'t implemented in conversion\n")
7090 def convertTextures(basename, texs, type="float", channel="col", val=1.0):
7093 isImagemap = (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!="")
7094 if channel == "col":
7095 if texture.flags & Texture.Flags["COLORBAND"] > 0:
7096 cbLow, cbHigh = convertColorband(texture.colorband)
7097 val1, alpha1, val2, alpha2 = (cbLow[0],cbLow[1],cbLow[2]), cbLow[3]*tex.colfac, (cbHigh[0], cbHigh[1], cbHigh[2]), cbHigh[3]*tex.colfac
7099 lum1, lum2 = (val1[0]+val1[1]+val1[2])/3.0, (val2[0]+val2[1]+val2[2])/3.0
7100 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)
7101 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
7102 else: val1, alpha1, val2, alpha2 = tex.col, 0.0, tex.col, tex.colfac
7103 elif channel == "nor": val1, alpha1, val2, alpha2 = tex.norfac * 0.01, 0.0, tex.norfac * 0.01, 1.0
7104 else: val1, alpha1, val2, alpha2 = 1.0, 0.0, 1.0, tex.varfac
7105 if (tex.neg)^((channel=="nor") and (tex.mtNor<0)): val1, alpha1, val2, alpha2 = val2, alpha2, val1, alpha1
7106 luxProp(mat, dot(basename)+"textured", "").set("true")
7109 if (alpha1 < 1.0) or (alpha2 < 1.0): # texture with transparency
7110 luxProp(mat, dot(basename)+"texture", "").set("mix")
7111 if alpha1 == alpha2: # constant alpha
7112 luxProp(mat, ddot(basename)+"amount.value", 1.0).set(alpha1)
7114 createLuxTexture(ddot(basename)+"amount", tex)
7115 luxProp(mat, ddot(basename)+"amount:tex1.value", 1.0).set(alpha1)
7116 luxProp(mat, ddot(basename)+"amount:tex2.value", 1.0).set(alpha2)
7117 # transparent to next texture
7118 name = ddot(basename)+"tex1"
7120 convertTextures(ddot(basename)+"tex1", texs, type, channel, val)
7122 if type=="float": luxProp(mat, ddot(basename)+"tex1.value", 1.0).set(val)
7123 else: luxProp(mat, ddot(basename)+"tex1.value", "1.0 1.0 1.0").setRGB((val[0], val[1], val[2]))
7124 name = ddot(basename)+"tex2"
7125 if val1 == val2: # texture with different colors / value
7126 if type == "col": luxProp(mat, dot(name)+"value", "1.0 1.0 1.0").setRGB(val1)
7127 else: luxProp(mat, dot(name)+"value", 1.0).set(val1)
7129 createLuxTexture(name, tex)
7130 if type == "col": luxProp(mat, ddot(name)+"tex1.value", "1.0 1.0 1.0").setRGB(val1)
7131 else: luxProp(mat, ddot(name)+"tex1.value", 1.0).set(val1)
7132 if type == "col": luxProp(mat, ddot(name)+"tex2.value", "1.0 1.0 1.0").setRGB(val2)
7133 else: luxProp(mat, ddot(name)+"tex2.value", 1.0).set(val2)
7136 def convertDiffuseTexture(name):
7138 for tex in mat.getTextures():
7139 if tex and (tex.mapto & Texture.MapTo["COL"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
7141 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
7142 convertTextures(name, texs, "col", "col", (mat.R, mat.G, mat.B))
7143 def convertSpecularTexture(name):
7145 for tex in mat.getTextures():
7146 if tex and (tex.mapto & Texture.MapTo["CSP"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
7148 luxProp(mat, name, "").setRGB((mat.ref*mat.spec, mat.ref*mat.spec, mat.ref*mat.spec))
7149 convertTextures(name, texs, "col", "col", (mat.specR, mat.specG, mat.specB))
7150 def convertMirrorTexture(name):
7152 for tex in mat.getTextures():
7153 if tex and (tex.mapto & Texture.MapTo["CMIR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
7155 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
7156 convertTextures(name, texs, "col", "col", (mat.mirR, mat.mirG, mat.mirB))
7157 def convertBumpTexture(basename):
7159 for tex in mat.getTextures():
7160 if tex and (tex.mapto & Texture.MapTo["NOR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
7162 name = basename+":bumpmap"
7163 luxProp(mat, basename+".usebump", "").set("true")
7164 luxProp(mat, dot(name)+"textured", "").set("true")
7165 luxProp(mat, name, "").set(1.0)
7166 convertTextures(name, texs, "float", "nor", 0.0)
7168 def makeMatte(name):
7169 luxProp(mat, dot(name)+"type", "").set("matte")
7170 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
7171 convertDiffuseTexture(name+":Kd")
7172 convertBumpTexture(name)
7173 def makeGlossy(name, roughness):
7174 luxProp(mat, dot(name)+"type", "").set("glossy")
7175 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
7176 luxProp(mat, name+":Ks", "").setRGB((mat.specR*mat.spec*0.5, mat.specG*mat.spec*0.5, mat.specB*mat.spec*0.5))
7177 luxProp(mat, name+":uroughness", 0.0).set(roughness)
7178 luxProp(mat, name+":vroughness", 0.0).set(roughness)
7179 convertDiffuseTexture(name+":Kd")
7180 convertSpecularTexture(name+":Ks")
7181 convertBumpTexture(name)
7182 def makeMirror(name):
7183 luxProp(mat, dot(name)+"type", "").set("mirror")
7184 luxProp(mat, name+":Kr", "").setRGB((mat.mirR, mat.mirG, mat.mirB))
7185 convertMirrorTexture(name+":Kr")
7186 convertBumpTexture(name)
7187 def makeGlass(name):
7188 luxProp(mat, dot(name)+"type", "").set("glass")
7189 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
7190 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
7191 luxProp(mat, name+":index.iorusepreset", "").set("false")
7192 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
7193 convertMirrorTexture(name+":Kr")
7194 convertDiffuseTexture(name+":Kt")
7195 convertBumpTexture(name)
7196 def makeRoughglass(name, roughness):
7197 luxProp(mat, dot(name)+"type", "").set("roughglass")
7198 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
7199 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
7200 luxProp(mat, name+":index.iorusepreset", "").set("false")
7201 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
7202 luxProp(mat, name+":uroughness", 0.0).set(roughness)
7203 luxProp(mat, name+":vroughness", 0.0).set(roughness)
7204 convertMirrorTexture(name+":Kr")
7205 convertDiffuseTexture(name+":Kt")
7206 convertBumpTexture(name)
7207 print("convert Blender material \"%s\" to LuxRender material"%(mat.name))
7208 mat.properties['luxblend'] = {}
7209 if mat.emit > 0.0001:
7210 luxProp(mat, "type", "").set("light")
7211 luxProp(mat, "light.l", "").setRGB((mat.R, mat.G, mat.B))
7212 luxProp(mat, "light.gain", 1.0).set(mat.emit)
7215 if not(mat.mode & Material.Modes.RAYTRANSP): alpha = 1.0
7216 alpha0name, alpha1name = "", ""
7217 if (alpha > 0.0) and (alpha < 1.0):
7218 luxProp(mat, "type", "").set("mix")
7219 luxProp(mat, ":amount", 0.0).set(alpha)
7220 alpha0name, alpha1name = "mat2", "mat1"
7222 mirror = mat.rayMirr
7223 if not(mat.mode & Material.Modes.RAYMIRROR): mirror = 0.0
7224 mirror0name, mirror1name = alpha1name, alpha1name
7225 if (mirror > 0.0) and (mirror < 1.0):
7226 luxProp(mat, dot(alpha1name)+"type", "").set("mix")
7227 luxProp(mat, alpha1name+":amount", 0.0).set(1.0 - mirror)
7228 mirror0name, mirror1name = ddot(alpha1name)+"mat1", ddot(alpha1name)+"mat2"
7230 if mat.glossMir < 1.0: makeGlossy(mirror1name, 1.0-mat.glossMir)
7231 else: makeMirror(mirror1name)
7233 if mat.spec > 0.0: makeGlossy(mirror0name, math.sqrt(2.0/(mat.hard+2.0)))
7234 else: makeMatte(mirror0name)
7236 if mat.glossTra < 1.0: makeRoughnessGlass(alpha0name, 1.0-mat.glossTra**2)
7237 else: makeGlass(alpha0name)
7239 def convertAllMaterials():
7240 if Draw.PupMenu(' OK?%t|Are you sure to convert all materials, replacing the current LuxRender material definitions?%x1') == 1:
7241 for mat in Material.Get(): convertMaterial(mat)
7246 ### Connect LRMDB ###
7247 ConnectLrmdb = False
7249 import socket # try import of socket library
7251 def downloadLRMDB(mat, id):
7253 DrawProgressBar(0.0,'Getting Material #'+id)
7255 HOST = 'webserver' #'www.luxrender.net'
7256 GET = '/lrmdb/en/material/download/'+id+'/'+LBX_VERSION
7258 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7259 sock.connect((HOST, PORT))
7260 sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST))
7261 data = sock.recv(1024)
7265 data = sock.recv(1024)
7267 if str.split("\n", 1)[0].find("200") < 0:
7268 print("ERROR: server error: %s"%(str.split("\n",1)[0]))
7270 str = (str.split("\r\n\r\n")[1]).strip()
7271 if (str[0]=="{") and (str[-1]=="}"):
7272 return str2MatTex(str)
7273 print("ERROR: downloaded data is not a material or texture:\n%s"%str)
7275 print("ERROR: download failed")
7277 DrawProgressBar(1.0,'')
7279 print("ERROR: material id is not valid")
7283 #===========================================================================
7285 #===========================================================================
7287 #---------------------------------------------------------------------------
7289 import cookielib, urllib2, xmlrpclib
7291 #---------------------------------------------------------------------------
7293 # https://fedorahosted.org/python-bugzilla/browser/bugzilla.py?rev=e6f699f06e92b1e49b1b8d2c8fbe89d9425a4a9a
7294 class CookieTransport(xmlrpclib.Transport):
7296 A subclass of xmlrpclib.Transport that supports cookies.
7303 # Cribbed from xmlrpclib.Transport.send_user_agent
7304 def send_cookies(self, connection, cookie_request):
7306 Send all the cookie data that we have received
7309 if self.cookiejar is None:
7310 self.cookiejar = cookielib.CookieJar()
7311 elif self.cookiejar:
7312 # Let the cookiejar figure out what cookies are appropriate
7313 self.cookiejar.add_cookie_header(cookie_request)
7314 # Pull the cookie headers out of the request object...
7316 for header, value in cookie_request.header_items():
7317 if header.startswith('Cookie'):
7318 cookielist.append([header, value])
7319 # ...and put them over the connection
7320 for header, value in cookielist:
7321 connection.putheader(header, value)
7323 # This is the same request() method from xmlrpclib.Transport,
7324 # with a couple additions noted below
7325 def request(self, host, handler, request_body, verbose=0):
7330 host_connection = self.make_connection(host)
7332 host_connection.set_debuglevel(1)
7334 # ADDED: construct the URL and Request object for proper cookie handling
7335 request_url = "%s://%s/" % (self.scheme, host)
7336 cookie_request = urllib2.Request(request_url)
7338 self.send_request(host_connection, handler, request_body)
7339 self.send_host(host_connection, host)
7341 # ADDED. creates cookiejar if None.
7342 self.send_cookies(host_connection, cookie_request)
7343 self.send_user_agent(host_connection)
7344 self.send_content(host_connection, request_body)
7346 errcode, errmsg, headers = host_connection.getreply()
7348 # ADDED: parse headers and get cookies here
7349 class CookieResponse:
7351 fake a response object that we can fill with the headers above
7354 def __init__(self, headers):
7355 self.headers = headers
7360 cookie_response = CookieResponse(headers)
7362 # Okay, extract the cookies from the headers
7363 self.cookiejar.extract_cookies(cookie_response, cookie_request)
7365 # And write back any changes
7366 # DH THIS DOESN'T WORK
7367 # self.cookiejar.save(self.cookiejar.filename)
7370 raise xmlrpclib.ProtocolError(
7376 self.verbose = verbose
7379 sock = host_connection._conn.sock
7380 except AttributeError:
7383 return self._parse_response(host_connection.getfile(), sock)
7386 #===========================================================================
7388 #===========================================================================
7390 host = 'http://webserver/lrmdb/ixr' #'http://www.luxrender.net/lrmdb/ixr'
7398 last_error_str = None
7400 def last_error(self):
7401 return self.last_error_str #'LRMDB Connector: %s' %
7405 result = self.SERVER.user.login(
7412 self.logged_in = True
7415 self.last_error_str = 'Login Failed'
7416 self.logged_in = False
7419 def submit_object(self, mat, basekey, tex):
7420 if not self.check_creds(): return False
7423 result = 'Unknown Error'
7426 name = Draw.PupStrInput('Name: ', '', 32)
7430 result = self.SERVER.object.submit(
7432 MatTex2dict( getMatTex(mat, basekey, tex), tex )
7434 if result is not True:
7438 except Exception, err:
7439 self.last_error_str = 'Submit failed: %s' % result
7444 def check_creds(self):
7445 if self.SERVER is None:
7447 self.SERVER = xmlrpclib.ServerProxy(self.host, transport=CookieTransport())
7449 self.last_error_str = 'ServerProxy init failed'
7453 if not self.logged_in:
7454 #if self.username is "":
7455 self.request_username()
7457 #if self.password is "":
7458 self.request_password()
7464 def request_username(self):
7465 self.username = Draw.PupStrInput("Username:", self.username, 32)
7467 def request_password(self):
7468 self.password = Draw.PupStrInput("Password:", self.password, 32)
7470 lrmdb_connector = lrmdb()
7473 except: print("WARNING: LRMDB support not available")
7477 ### MatTex functions ###
7478 ### MatTex : is a dictionary of material or texture properties
7480 def getMatTex(mat, basekey='', tex=False):
7481 global usedproperties, usedpropertiesfilterobj
7483 usedpropertiesfilterobj = mat
7484 if basekey.startswith('named_volumes:'):
7485 luxNamedVolumeTexture(basekey[basekey.find(':')+1:basekey.find('.')])
7489 for k,v in usedproperties.items():
7490 if k[:len(basekey)]==basekey:
7491 if k[-9:] != '.textured':
7492 name = k[len(basekey):]
7493 if name == ".type": name = "type"
7495 dict["__type__"] = ["material","texture"][bool(tex)]
7498 def putMatTex(mat, dict, basekey='', tex=None):
7499 if dict and (tex!=None) and (tex ^ (dict.has_key("__type__") and (dict["__type__"]=="texture"))):
7500 print("ERROR: Can't apply %s as %s"%(["texture","material"][bool(tex)],["material","texture"][bool(tex)]))
7503 # remove all current properties in mat that starts with basekey
7505 d = mat.properties['luxblend']
7506 for k,v in d.convert_to_pyobject().items():
7508 if k[:7]=="__hash:": # decode if entry is hashed (cause of 32chars limit)
7511 if kn[:len(basekey)]==basekey:
7512 del mat.properties['luxblend'][k]
7513 except: print("error") # pass
7515 scn = Scene.GetCurrent()
7517 for k, v in dict.items():
7518 if k == '__volumes__':
7519 for volume_prop, volume_data in v.items():
7520 volumes = listNamedVolumes()
7521 # new id and name if existing are occupied
7522 newId = max(volumes.values())+1 if volumes else 1
7523 newName = volume_data['name'] if not volumes.has_key(volume_data['name']) else volume_data['name']+'_new'
7524 volPrefix = 'named_volumes:%s.' % newId
7525 # replacing dict items for the next pass ('assign loaded' below)
7526 dict['%s_vol_id' % volume_prop] = newId
7527 dict['%s_vol_name' % volume_prop] = newName
7528 # assigning global properties
7529 luxProp(scn, volPrefix+'id', 0).set(newId)
7530 luxProp(scn, volPrefix+'name', '').set(newName)
7531 for volKey, volVal in volume_data.items():
7532 if not volKey in ['id', 'name']:
7533 luxProp(scn, volPrefix+volKey, None).set(volVal)
7534 # assign loaded properties
7535 for k,v in dict.items():
7536 if k in ['Exterior_vol_guid', 'Interior_vol_guid']:
7539 if (basekey!="") and (k=="type"): k = ".type"
7540 # zuegs: following two lines should fix issue http://www.luxrender.net/forum/viewtopic.php?f=16&t=1618&p=14512#p14512
7541 if (basekey!="") and ((k[0]!=".") and (k[0]!=":")): k = ":"+k
7542 if (basekey=="") and (k[0:4]==":mat"): k = k[1:]
7543 luxProp(mat, basekey+k, None).set(v)
7544 if k[-8:] == '.texture':
7545 luxProp(mat, basekey+k[:-8]+'.textured', 'false').set('true')
7549 LBX_VERSION = '0.71'
7551 def MatTex2dict(d, tex = None):
7554 if LBX_VERSION == '0.6':
7556 if tex is not None and tex == True:
7557 d['LUX_DATA'] = 'TEXTURE'
7559 d['LUX_DATA'] = 'MATERIAL'
7561 d['LUX_VERSION'] = '0.6'
7565 elif LBX_VERSION in ['0.7', '0.71']:
7566 def makeDefinition(d):
7569 if type(d[k]) == types.IntType:
7571 if type(d[k]) == types.FloatType:
7573 if type(d[k]) == types.BooleanType:
7575 if type(d[k]) == types.StringType:
7580 if l==None or len(l)!=3:
7585 o.append([ t, k, d[k] ])
7588 if LBX_VERSION == '0.71':
7590 'type': d['__type__'],
7591 'version': LBX_VERSION,
7592 'definition': makeDefinition(d),
7595 ['string', 'generator', 'luxblend'],
7599 for volume_prop in ['Exterior', 'Interior']:
7600 if d.has_key('%s_vol_id' % volume_prop):
7601 volume = makeDefinition(getNamedVolume(d['%s_vol_id' % volume_prop]))
7602 lbx['volumes'].append({
7603 'type': volume_prop,
7604 'definition': volume,
7605 'version': LBX_VERSION
7608 elif LBX_VERSION == '0.7':
7610 'type': d['__type__'],
7611 'version': LBX_VERSION,
7612 'definition': makeDefinition(d),
7614 ['string', 'generator', 'luxblend'],
7620 def format_dictStr(dictStr):
7626 for char in dictStr:
7627 if char in ['}', ']']:
7630 for j in range(0,pos):
7635 if char in [',', '{', '[']:
7637 if char in ['{', '[']:
7639 for j in range(0,pos):
7645 def MatTex2str(d, tex = None):
7648 if LBX_VERSION == '0.6':
7649 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace(", \'", ",\n\'")
7651 elif LBX_VERSION in ['0.7', '0.71']:
7652 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace("], \'", "],\r\n\'").replace("[","\r\n\t[")
7655 def str2MatTex(s, tex = None): # todo: this is not absolutely save from attacks!!!
7659 if (s[0]=='{') and (s[-1]=='}'):
7660 d = eval(s, dict(__builtins__=None))
7661 if type(d)==types.DictType:
7662 def lb_list_to_dict(list):
7664 for t, k, v in list:
7671 if LBX_VERSION == '0.6':
7673 if tex is not None and tex == True:
7674 test_str = 'TEXTURE'
7676 test_str = 'MATERIAL'
7678 if ('LUX_DATA' in d.keys() and d['LUX_DATA'] == test_str) \
7679 and ('LUX_VERSION' in d.keys() and (d['LUX_VERSION'] == '0.6' or d['LUX_VERSION'] == 0.6)):
7682 reason = 'Missing/incorrect metadata'
7684 elif LBX_VERSION == '0.7':
7686 if ('version' in d.keys() and d['version'] in ['0.6', '0.7']) \
7687 and ('type' in d.keys() and d['type'] in ['material', 'texture']) \
7688 and ('definition' in d.keys()):
7690 definition = lb_list_to_dict(d['definition'])
7692 if 'metadata' in d.keys():
7693 definition.update( lb_list_to_dict(d['metadata']) )
7696 reason = 'Incorrect LBX definition data'
7698 reason = 'Missing/incorrect metadata'
7700 elif LBX_VERSION == '0.71':
7702 if ('version' in d.keys() and d['version'] in ['0.6', '0.7', '0.71']) \
7703 and ('type' in d.keys() and d['type'] in ['material', 'texture']) \
7704 and ('definition' in d.keys()):
7706 definition = lb_list_to_dict(d['definition'])
7708 if 'metadata' in d.keys():
7709 definition.update( lb_list_to_dict(d['metadata']) )
7710 if 'volumes' in d.keys():
7711 definition['__volumes__'] = {}
7712 for volume in d['volumes']:
7713 definition['__volumes__'][volume['type']] = lb_list_to_dict(volume['definition'])
7716 reason = 'Incorrect LBX definition data'
7718 reason = 'Missing/incorrect metadata'
7720 reason = 'Unknown LBX version'
7722 reason = 'Not a parsed dict'
7724 reason = 'Not a stored dict'
7727 print("ERROR: string to material/texture conversion failed: %s" % reason)
7731 luxclipboard = None # global variable for copy/paste content
7732 def showMatTexMenu(mat, basekey='', tex=False):
7733 global luxclipboard, ConnectLrmdb
7734 if tex: menu="Texture menu:%t"
7735 else: menu="Material menu:%t"
7738 if luxclipboard and (not(tex) ^ (luxclipboard["__type__"]=="texture")): menu +="|Paste%x2"
7741 menu += "|Load LBT%x3|Save LBT%x4"
7743 menu += "|Load LBM%x3|Save LBM%x4"
7745 menu += "|Download from DB%x5" #not(tex) and
7746 # XXX temporarily disabling for glass2
7747 if luxProp(mat, basekey+'type', '').get() != 'glass2': menu += "|Upload to DB%x6"
7750 # menu += "|%l|dump material%x99|dump clipboard%x98"
7751 r = Draw.PupMenu(menu)
7753 luxclipboard = getMatTex(mat, basekey, tex)
7754 elif r==2: putMatTex(mat, luxclipboard, basekey, tex)
7756 scn = Scene.GetCurrent()
7758 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
7760 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
7762 scn = Scene.GetCurrent()
7764 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
7766 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
7769 id = Draw.PupStrInput("Material ID:", "", 32)
7771 id = Draw.PupStrInput("Texture ID:", "", 32)
7772 if id: putMatTex(mat, downloadLRMDB(mat, id), basekey, tex)
7774 global lrmdb_connector
7775 if not lrmdb_connector.submit_object(mat, basekey, tex):
7776 msg = lrmdb_connector.last_error()
7779 Draw.PupMenu("Upload: "+msg+".%t|OK")
7781 resetMatTex(mat, basekey)
7783 # for k,v in mat.properties['luxblend'].convert_to_pyobject().items(): print(k+"="+repr(v))
7785 # for k,v in luxclipboard.items(): print(k+"="+repr(v))
7790 def resetMatTex(mat, basekey=''):
7791 if not mat.properties.has_key('luxblend'): return
7792 for k, v in mat.properties['luxblend'].convert_to_pyobject().items():
7794 if k[:7] == '__hash:':
7795 kn = v.split(' = ')[0]
7796 if kn.startswith(basekey) and kn != basekey:
7797 del mat.properties['luxblend'][k]
7800 def saveMatTex(mat, fn, basekey='', tex=False):
7802 d = getMatTex(mat, basekey, tex)
7803 file = open(fn, 'w')
7804 file.write(MatTex2str(d, tex))
7806 if LuxIsGUI: Draw.Redraw()
7809 def loadMatTex(mat, fn, basekey='', tex=None):
7811 file = open(fn, 'rU')
7814 data = str2MatTex(data, tex)
7815 putMatTex(mat, data, basekey, tex)
7816 if LuxIsGUI: Draw.Redraw()
7819 def batchRenamePaths(scn):
7820 dryrun = luxProp(scn, 'batch_rename_dryrun', False)
7821 searchSaved = luxProp(scn, 'batch_rename_search', '')
7822 search = Draw.PupStrInput('path substring to search for: ', searchSaved.get(), 100)
7823 searchSaved.set(search)
7826 Blender.Window.QRedrawAll()
7831 metals = ['aluminium', 'amorphous carbon', 'silver', 'gold', 'copper']
7832 for item in [scn] + Material.Get():
7833 if item.properties.has_key('luxblend'):
7834 for k, v in item.properties['luxblend'].convert_to_pyobject().items():
7836 if k[:7] == '__hash:':
7837 kn, v = v.split(' = ')
7838 if type(v) is str and kn.endswith(('.filename', '.name')) and not (kn.endswith('.name') and v in metals) \
7839 and not (kn.endswith('.name') and kn.startswith('named_volumes:')):
7840 if v.find(search) < 0: misses.append([item, kn])
7841 else: collection.append([item, kn])
7843 if not len(collection):
7844 Draw.PupMenu('Search substring not found in resources paths%t|OK%x1')
7845 Blender.Window.QRedrawAll()
7848 replaceSaved = luxProp(scn, 'batch_rename_replace', '')
7849 replace = Draw.PupStrInput('replace with: ', replaceSaved.get(), 100)
7850 replaceSaved.set(replace)
7852 r = Draw.PupMenu(' OK?%t|Replace "'+search+'" substring with "'+replace+'" in '+str(len(collection))+' of '+str(len(collection)+len(misses))+' path properties%x1')
7855 if dryrun.get() == 'true':
7856 print '--------------- DRY RUN ---------------'
7857 print 'Begin batch search & replace in paths:'
7858 print '("%s" to "%s" in %s properties)' % (search, replace, len(collection))
7859 for item, kn in collection:
7860 v_old = luxProp(item, kn, '').get()
7861 v_new = v_old.replace(search, replace)
7862 print '%s, %s' % (item, kn)
7863 print "\told:", v_old
7864 print "\tnew:", v_new
7865 if dryrun.get() != 'true':
7866 luxProp(item, kn, '').set(v_new)
7868 print '---------------------------------------'
7869 print '%s properties not affected:' % len(misses)
7870 for item, kn in misses:
7871 print '%s, %s' % (item, kn)
7872 if dryrun.get() == 'true':
7873 print '--------------- DRY RUN ---------------'
7876 Blender.Window.QRedrawAll()
7880 def flipMixMat(mat, basekey):
7881 # flip mix material slots
7882 if luxProp(mat, 'type', '').get() == 'mix':
7886 r = re.compile(basekey+r'(\:mat[12])+')
7887 basekey = basekey+':'
7889 r = re.compile(r'mat[12](\:mat[12])*')
7891 s = [{}, {}] # we'll store slots property items here for later processing
7892 p = [{}, {}] # and this is for cached preview images
7893 d = mat.properties['luxblend']
7894 for k, v in d.convert_to_pyobject().items():
7896 if k[:7] == '__hash:':
7899 # select required slot properties at the appropriate level
7900 for i in range(0, 2):
7901 if kn[:len(basekey)+4] == basekey+'mat'+str(i+1):
7903 #print 'slot'+str(i+1)+' (saved to dict '+str(i^1)+'):', k, '=', v
7905 del mat.properties['luxblend'][k] # remove original item
7908 pk = k[0:r.match(k).end()]
7909 hashkey = (mat.name+':'+pk+'.').__hash__()
7910 if not p[i^1].has_key(pk) and previewCache.has_key(hashkey):
7911 #print 'preview for slot'+str(i+1)+' key: ', pk, '(saved to dict '+str(i^1)+')'
7912 p[i^1][pk] = previewCache[hashkey]
7913 del previewCache[hashkey] # remove original item
7914 except AttributeError:
7917 for i in range(0, 2):
7919 for k, v in s[i].items():
7920 if k[:7] == '__hash:':
7922 newkey = l[0].replace(basekey+'mat'+str((i+1)^3), basekey+'mat'+str(i+1), 1)
7923 hexkey = '__hash:'+hex(newkey.__hash__()).replace('0x', '')
7925 #print k, '>>>', hexkey, '=', newkey, '=', v
7926 mat.properties['luxblend'][hexkey] = newkey+' = '+str(v)
7928 newkey = k.replace(basekey+'mat'+str((i+1)^3), basekey+'mat'+str(i+1), 1)
7929 #print k, '>>>', newkey, '=', v
7930 mat.properties['luxblend'][newkey] = str(v)
7931 # renaming cached previews keys
7932 for k, v in p[i].items():
7933 pk = mat.name+':'+k+'.'
7934 newpk = k.replace(basekey+'mat'+str((i+1)^3), basekey+'mat'+str(i+1), 1)
7935 newpk = mat.name+':'+newpk+'.'
7936 #print pk, '('+str(pk.__hash__())+')', '>>>', newpk, '('+str(newpk.__hash__())+')'
7937 previewCache[newpk.__hash__()] = v
7939 def showVolumesMenu(mat, volume_prop, r=None):
7940 scn = Scene.GetCurrent()
7941 active_volume = getNamedVolume(luxProp(mat, '%s_vol_id' % (volume_prop), 0).get())
7942 menu = "Manage mediums:%t|Create new medium%x1|Copy selected%x2"
7943 if active_volume['name'] != 'world *':
7944 menu += "|Rename selected%x3"
7946 if not r: r = Draw.PupMenu(menu)
7949 name = Draw.PupStrInput('medium name: ', '')
7950 vols = listNamedVolumes()
7951 if vols.has_key(name) or name == 'world *':
7952 Draw.PupMenu('ERROR: Medium name already exists%t|OK%x1')
7953 Blender.Window.QRedrawAll()
7956 newId = vols and max(vols.values())+1 or 1
7957 luxProp(scn, 'named_volumes:%s.name' % newId, 0).set(name)
7958 luxProp(mat, '%s_vol_id' % (volume_prop), 0).set(newId)
7959 luxProp(mat, '%s_vol_name' % (volume_prop), '').set(name)
7960 luxProp(mat, '%s_vol_guid' % (volume_prop), '').set(luxUID)
7961 Blender.Window.QRedrawAll()
7964 # copy existing volume
7965 name = Draw.PupStrInput('copy to name: ', '')
7966 vols = listNamedVolumes()
7967 if name == active_volume['name'] or name == '':
7968 Blender.Window.QRedrawAll()
7970 if vols.has_key(name):
7971 r = Draw.PupMenu(' OK?%t|Replace existing medium%x1')
7973 volProps = getNamedVolume(vols[name])
7975 for n in volProps.keys():
7976 if not n in ['name', 'id']:
7977 luxProp(scn, 'named_volumes:%s.%s'%(volId,n), '').delete()
7979 Blender.Window.QRedrawAll()
7982 volId = vols and max(vols.values())+1 or 1
7983 luxProp(scn, 'named_volumes:%s.name' % volId, 0).set(name)
7984 for k, v in active_volume.items():
7985 if not k in ['name', 'id']:
7986 luxProp(scn, 'named_volumes:%s.%s'%(volId,k), '').set(v)
7987 luxProp(mat, '%s_vol_id' % (volume_prop), 0).set(volId)
7988 luxProp(mat, '%s_vol_name' % (volume_prop), '').set(name)
7989 Blender.Window.QRedrawAll()
7992 # rename existing volume
7993 name = Draw.PupStrInput('new name: ', active_volume['name'])
7994 vols = listNamedVolumes()
7995 if name == 'world *':
7996 Draw.PupMenu('ERROR: Impossible to rename to the world medium, use Copy instead%t|OK%x1')
7997 Blender.Window.QRedrawAll()
7999 elif name == active_volume['name'] or name == '':
8000 Blender.Window.QRedrawAll()
8002 if vols.has_key(name):
8003 r = Draw.PupMenu(' OK?%t|Replace existing medium%x1')
8005 volProps = getNamedVolume(vols[name])
8006 for n in volProps.keys():
8007 luxProp(scn, 'named_volumes:%s.%s'%(vols[name],n), '').delete()
8009 Blender.Window.QRedrawAll()
8011 luxProp(scn, 'named_volumes:%s.name' % active_volume['id'], 0).set(name)
8012 luxProp(mat, '%s_vol_name' % (volume_prop), '').set(name)
8013 Blender.Window.QRedrawAll()
8016 # unlinking a volume
8017 luxProp(mat, '%s_vol_name' % (volume_prop), '').set('world *')
8018 luxProp(mat, '%s_vol_id' % (volume_prop), 0).set(0)
8019 Blender.Window.QRedrawAll()
8024 def setactivemat(mat):
8032 self.position = 0 # current position at top (inside 0..height-viewHeight)
8033 self.height = 0 # total height of the content
8034 self.viewHeight = 0 # height of window
8035 self.x = 0 # horizontal position of the scrollbar
8036 self.scrolling = self.over = False # start without scrolling ;)
8037 def calcRects(self):
8038 # Blender doesn't give us direct access to the window size yet, but it does set the
8039 # GL scissor box for it, so we can get the size from that. (thx to Daniel Dunbar)
8040 size = BGL.Buffer(BGL.GL_FLOAT, 4)
8041 BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
8042 size = size.list # [winx, winy, width, height]
8043 self.winrect = size[:]
8044 self.viewHeight = size[3]
8045 size[0], size[1] = size[2]-20, 0 # [scrollx1, scrolly1, scrollx2, scrolly2]
8047 if self.position < 0: self.position = 0
8048 if self.height < self.viewHeight: self.height = self.viewHeight
8049 if self.position > self.height-self.viewHeight: self.position = self.height-self.viewHeight
8050 self.factor = (size[3]-size[1]-4)/self.height
8051 self.sliderRect = [size[0]+2, size[3]-2-(self.position+self.viewHeight)*self.factor, size[2]-2, size[3]-2-self.position*self.factor]
8054 BGL.glColor3f(0.5,0.5,0.5); BGL.glRectf(self.rect[0],self.rect[1],self.rect[2],self.rect[3])
8055 if self.over or self.scrolling: BGL.glColor3f(1.0,1.0,0.7)
8056 else: BGL.glColor3f(0.7,0.7,0.7)
8057 BGL.glRectf(self.sliderRect[0],self.sliderRect[1],self.sliderRect[2],self.sliderRect[3])
8059 return self.viewHeight+self.position
8060 def scroll(self, delta):
8061 self.position = self.position + delta
8066 coord, buttons = Window.GetMouseCoords(), Window.GetMouseButtons()
8067 over = (coord[0]>=self.winrect[0]+self.rect[0]) and (coord[0]<=self.winrect[0]+self.rect[2]) and \
8068 (coord[1]>=self.winrect[1]+self.rect[1]) and (coord[1]<=self.winrect[1]+self.rect[3])
8069 if Window.MButs.L and buttons > 0:
8071 if self.factor > 0: self.scroll((self.lastcoord[1]-coord[1])/self.factor)
8074 self.scrolling = True
8075 self.lastcoord = coord
8076 elif self.scrolling:
8077 self.scrolling = False
8079 if self.over != over: Draw.Redraw()
8082 scrollbar = scrollbar()
8087 global icon_luxblend
8090 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
8092 y = int(scrollbar.getTop()) # 420
8093 BGL.glColor3f(0.1,0.1,0.1); BGL.glRectf(0,0,440,y)
8094 BGL.glColor3f(1.0,0.5,0.0); BGL.glRasterPos2i(130,y-21); Draw.Text("v%s"%__version__)
8095 BGL.glColor3f(0.9,0.9,0.9)
8097 drawLogo(icon_luxblend, 6, y-25)
8099 scn = Scene.GetCurrent()
8101 luxUID = luxGenUID(scn)
8102 luxpage = luxProp(scn, "page", 0)
8106 BGL.glRasterPos2i(10,y-45); Draw.Text("Render presets:")
8107 luxpreset = luxProp(scn, "preset", "1C - Final - medium MLT/Path Tracing (indoor) (recommended)")
8108 presets = getScenePresets()
8109 presetskeys = presets.keys()
8111 presetskeys.insert(0, "")
8112 presetsstr = "presets: %t"
8113 for i, v in enumerate(presetskeys): presetsstr = "%s %%x%d|%s"%(v, i, presetsstr)
8114 try: i = presetskeys.index(luxpreset.get())
8115 except ValueError: i = 0
8116 Draw.Menu(presetsstr, evtLuxGui, 110, y-50, 220, 18, i, "", lambda e,v: luxpreset.set(presetskeys[v]))
8117 Draw.Button("save", evtSavePreset, 330, y-50, 40, 18, "create a render-settings preset")
8118 Draw.Button("del", evtDeletePreset, 370, y-50, 40, 18, "delete a render-settings preset")
8120 # if preset is selected load values
8121 if luxpreset.get() != "":
8123 d = presets[luxpreset.get()]
8124 for k,v in d.items(): scn.properties['luxblend'][k] = v
8127 Draw.Button("Material", evtLuxGui, 10, y-70, 80, 16, "", lambda e,v:luxpage.set(0))
8128 Draw.Button("Cam/Env", evtLuxGui, 90, y-70, 80, 16, "", lambda e,v:luxpage.set(1))
8129 Draw.Button("Render", evtLuxGui, 170, y-70, 80, 16, "", lambda e,v:luxpage.set(2))
8130 Draw.Button("Output", evtLuxGui, 250, y-70, 80, 16, "", lambda e,v:luxpage.set(3))
8131 Draw.Button("System", evtLuxGui, 330, y-70, 80, 16, "", lambda e,v:luxpage.set(4))
8132 if luxpage.get() == 0:
8133 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(10,y-74,90,y-70);BGL.glColor3f(0.9,0.9,0.9)
8134 obj = scn.objects.active
8136 if (obj.getType() == "Lamp"):
8137 ltype = obj.getData(mesh=1).getType() # data
8138 if (ltype == Lamp.Types["Area"]): luxLight("Area LIGHT", "", obj, gui, 0)
8139 elif (ltype == Lamp.Types["Spot"]): luxSpot("Spot LIGHT", "", obj, gui, 0)
8140 elif (ltype == Lamp.Types["Lamp"]): luxLamp("Point LIGHT", "", obj, gui, 0)
8142 matfilter = luxProp(scn, "matlistfilter", "false")
8143 mats = getMaterials(obj, True)
8144 if (activemat == None) and (len(mats) > 0):
8145 setactivemat(mats[0])
8146 if matfilter.get() == "false":
8147 mats = Material.Get()
8149 for i, v in enumerate(mats):
8150 if v==activemat: matindex = i
8151 matnames = [m.getName() for m in mats]
8152 menustr = "Material: %t"
8153 for i, v in enumerate(matnames): menustr = "%s %%x%d|%s"%(v, i, menustr)
8154 gui.newline("MATERIAL:", 8)
8155 r = gui.getRect(1.1, 1)
8156 Draw.Button("C", evtConvertMaterial, r[0]-gui.h, gui.y-gui.h, gui.h, gui.h, "convert Blender material to LuxRender material")
8157 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], matindex, "", lambda e,v: setactivemat(mats[v]))
8158 luxBool("", matfilter, "filter", "only show active object materials", gui, 0.5)
8160 Draw.Button("L", evtLoadMaterial, gui.x, gui.y-gui.h, gui.h, gui.h, "load a material preset")
8161 Draw.Button("S", evtSaveMaterial, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "save a material preset")
8162 Draw.Button("D", evtDeleteMaterial, gui.x+gui.h*2, gui.y-gui.h, gui.h, gui.h, "delete a material preset")
8164 setactivemat(mats[matindex])
8165 luxMaterial(activemat, gui)
8166 if luxpage.get() == 1:
8167 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(90,y-74,170,y-70);BGL.glColor3f(0.9,0.9,0.9)
8168 #cam = scn.getCurrentCamera()
8169 cam = scn.objects.camera
8171 r = gui.getRect(1.1, 1)
8172 luxCamera(cam.data, scn.getRenderingContext(), gui)
8174 luxEnvironment(scn, gui)
8175 if luxpage.get() == 2:
8176 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(170,y-74,250,y-70);BGL.glColor3f(0.9,0.9,0.9)
8177 r = gui.getRect(1.1, 1)
8178 luxSampler(scn, gui)
8180 luxSurfaceIntegrator(scn, gui)
8182 luxVolumeIntegrator(scn, gui)
8184 luxPixelFilter(scn, gui)
8185 if luxpage.get() == 3:
8186 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(250,y-74,330,y-70);BGL.glColor3f(0.9,0.9,0.9)
8187 r = gui.getRect(1.1, 1)
8189 if luxpage.get() == 4:
8190 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(330,y-74,410,y-70);BGL.glColor3f(0.9,0.9,0.9)
8193 luxAccelerator(scn, gui)
8194 gui.newline("MATERIALS:", 10)
8195 r = gui.getRect(2,1)
8196 Draw.Button("Convert all Blender materials", 0, r[0], r[1], r[2], r[3], "Convert all Blender materials in the scene to LuxRender materials", lambda e,v:convertAllMaterials())
8197 r = gui.getRect(1.5,1)
8198 Draw.Button('Batch replace of resources paths', 0, r[0], r[1], r[2], r[3], 'Batch search & replace of paths to imagemaps and other external resources', lambda e,v:batchRenamePaths(scn))
8199 luxBool('batch_rename_dryrun', luxProp(scn, 'batch_rename_dryrun', False), 'dry run', 'Print all normal output to the Blender console without actually replacing any path properties', gui, 0.5)
8200 gui.newline("SETTINGS:", 10)
8201 r = gui.getRect(2,1)
8202 Draw.Button("Save defaults", 0, r[0], r[1], r[2], r[3], "Save current settings as defaults", lambda e,v:saveluxdefaults())
8203 luxRemoveProps(scn, gui)
8205 if y > 0: y = 0 # bottom align of render button
8206 run = luxProp(scn, "run", "true")
8207 dlt = luxProp(scn, "default", "true")
8208 pipe = luxProp(scn, "pipe", "false")
8209 clay = luxProp(scn, "clay", "false")
8210 nolg = luxProp(scn, "nolg", "false")
8211 lxs = luxProp(scn, "lxs", "true")
8212 lxo = luxProp(scn, "lxo", "true")
8213 lxm = luxProp(scn, "lxm", "true")
8214 lxv = luxProp(scn, "lxv", "true")
8215 net = luxProp(scn, "netrenderctl", "false")
8216 donet = luxProp(scn, "donetrender", "true")
8218 global render_status_text
8219 global render_status
8221 if render_status == True:
8222 BGL.glRasterPos2i(10,y+20)
8223 Draw.Text(render_status_text)
8225 BGL.glRasterPos2i(10,y+5)
8226 Draw.Text(render_status_text, "tiny")
8228 def check_pipe_def_exclusion(m, v):
8230 dlt.set(["false","true"][bool(v)])
8232 if dlt.get() == 'true':
8235 pipe.set(["false","true"][bool(v)])
8237 if pipe.get() == 'true':
8240 if (run.get()=="true"):
8241 Draw.Button("Render", 0, 10, y+20, 100, 36, "Render image with LuxRender", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", True))
8242 Draw.Button("Render Anim", 0, 110, y+20, 100, 36, "Render animation with LuxRender", lambda e,v:CBluxAnimExport(dlt.get()=="true" or pipe.get()=="true", True))
8244 Draw.Button("Export", 0, 10, y+20, 100, 36, "Export", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", False))
8245 Draw.Button("Export Anim", 0, 110, y+20, 100, 36, "Export animation", lambda e,v:CBluxAnimExport(dlt.get()=="true" or pipe.get()=="true", False))
8247 Draw.Toggle("run", evtLuxGui, 265, y+40, 30, 16, run.get()=="true", "Start LuxRender after export", lambda e,v: run.set(["false","true"][bool(v)]))
8249 if (pipe.get() == 'false' and dlt.get() == 'true') or run.get()=='false':
8250 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))
8251 elif pipe.get() == 'true' and dlt.get() == 'false':
8252 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))
8254 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))
8255 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))
8257 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)]))
8258 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)]))
8260 if pipe.get() == "false":
8261 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)]))
8262 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)]))
8263 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)]))
8264 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)]))
8266 BGL.glColor3f(0.9, 0.9, 0.9)
8268 BGL.glRasterPos2i(330,y+5) ; Draw.Text("Press Q or ESC to quit.", "tiny")
8269 scrollbar.height = scrollbar.getTop() - y
8272 render_status_text = ''
8273 render_status = False
8288 def luxEvent(evt, val): # function that handles keyboard and mouse events
8289 global activeObject, activemat, activeEvent, lastEventTime, key_tabs
8290 if evt == Draw.ESCKEY or evt == Draw.QKEY:
8291 stop = Draw.PupMenu("OK?%t|Cancel export %x1")
8295 scn = Scene.GetCurrent()
8297 if scn.objects.active != activeObject:
8298 activeObject = scn.objects.active
8301 if (evt == Draw.MOUSEX) or (evt == Draw.MOUSEY): scrollbar.Mouse()
8302 if evt == Draw.WHEELUPMOUSE: scrollbar.scroll(-16)
8303 if evt == Draw.WHEELDOWNMOUSE: scrollbar.scroll(16)
8304 if evt == Draw.PAGEUPKEY: scrollbar.scroll(-50)
8305 if evt == Draw.PAGEDOWNKEY: scrollbar.scroll(50)
8307 # scroll to [T]op and [B]ottom
8308 if evt == Draw.TKEY:
8309 scrollbar.scroll(-scrollbar.position)
8310 if evt == Draw.BKEY:
8311 scrollbar.scroll(100000) # Some large number should be enough ?!
8313 # R key shortcut to launch render
8314 # E key shortcut to export current scene (not render)
8315 # P key shortcut to preview current material
8316 # These keys need time and process-complete locks
8317 if evt in [Draw.RKEY, Draw.EKEY, Draw.PKEY]:
8318 if activeEvent == None and (sys.time() - lastEventTime) > 5:
8319 lastEventTime = sys.time()
8320 if evt == Draw.RKEY:
8321 activeEvent = 'RKEY'
8322 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", True)
8324 if evt == Draw.EKEY:
8325 activeEvent = 'EKEY'
8326 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", False)
8328 if evt == Draw.PKEY:
8329 activeEvent = 'PKEY'
8330 if activemat != None:
8331 Preview_Update(activemat, '', True, 0, None, None, None)
8334 # Switch GUI tabs with number keys
8335 if evt in key_tabs.keys():
8336 luxProp(scn, "page", 0).set(key_tabs[evt])
8341 # Handle icon button events - note - radiance - this is a work in progress! :)
8342 # if evt == Draw.LEFTMOUSE and not val:
8343 # size=BGL.Buffer(BGL.GL_FLOAT, 4)
8344 # BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
8345 # size= [int(s) for s in size]
8346 # mx, my = Window.GetMouseCoords()
8347 # mousex = mx - size[0]
8348 # print("mousex = %i"%mousex)
8349 # #if((mousex > 2) and (mousex < 25)):
8350 # # Mouse clicked in left button bar
8351 # if((mousex > 399) and (mousex < 418)):
8352 # # Mouse clicked in right button bar
8353 # mousey = my - size[1] - scrollbar.position
8354 # print("mousey = %i"%mousey)
8357 def luxButtonEvt(evt): # function that handles button events
8358 global usedproperties, usedpropertiesfilterobj
8359 if evt == evtLuxGui:
8361 if evt == evtSavePreset:
8362 scn = Scene.GetCurrent()
8364 name = Draw.PupStrInput("preset name: ", "")
8367 usedpropertiesfilterobj = None
8368 luxSurfaceIntegrator(scn)
8373 # luxEnvironment(scn)
8374 saveScenePreset(name, usedproperties.copy())
8375 luxProp(scn, "preset", "").set(name)
8377 if evt == evtDeletePreset:
8378 presets = getScenePresets().keys()
8380 presetsstr = "delete preset: %t"
8381 for i, v in enumerate(presets): presetsstr += "|%s %%x%d"%(v, i)
8382 r = Draw.PupMenu(presetsstr, 20)
8384 saveScenePreset(presets[r], None)
8387 if evt == evtLoadMaterial:
8389 mats = getMaterialPresets()
8390 matskeys = mats.keys()
8392 matsstr = "load preset: %t"
8393 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
8394 r = Draw.PupMenu(matsstr, 20)
8398 # for k,v in mats[name].items(): activemat.properties['luxblend'][k] = v
8399 for k,v in mats[name].items(): luxProp(activemat, k, None).set(v)
8402 if evt == evtSaveMaterial:
8404 name = Draw.PupStrInput("preset name: ", "")
8407 usedpropertiesfilterobj = activemat
8408 luxMaterial(activemat)
8409 saveMaterialPreset(name, usedproperties.copy())
8411 if evt == evtDeleteMaterial:
8412 matskeys = getMaterialPresets().keys()
8414 matsstr = "delete preset: %t"
8415 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
8416 r = Draw.PupMenu(matsstr, 20)
8418 saveMaterialPreset(matskeys[r], None)
8420 if evt == evtConvertMaterial:
8421 if activemat: convertMaterial(activemat)
8423 if evt == evtLoadMaterial2:
8425 scn = Scene.GetCurrent()
8426 Window.FileSelector(lambda fn:loadMatTex(activemat, fn), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
8427 if evt == evtSaveMaterial2:
8429 scn = Scene.GetCurrent()
8430 Window.FileSelector(lambda fn:saveMaterial(activemat, fn), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
8433 def setFocus(target):
8434 currentscene = Scene.GetCurrent()
8435 camObj = currentscene.objects.camera # currentscene.getCurrentCamera()
8438 refLoc = (Object.GetSelected()[0]).getLocation()
8440 print("select an object to focus\n")
8442 refLoc = Window.GetCursorPos()
8444 refLoc = (Object.Get(target)).getLocation()
8445 dist = Mathutils.Vector(refLoc) - Mathutils.Vector(camObj.getLocation())
8446 camDir = camObj.getMatrix()[2]*(-1.0)
8447 camObj.getData(mesh=1).dofDist = (camDir[0]*dist[0]+camDir[1]*dist[1]+camDir[2]*dist[2])/camDir.length # data
8450 # Parse command line arguments for batch mode rendering if supplied
8455 batchindex = osys.argv.index('--batch')
8456 pyargs = osys.argv[osys.argv.index('--batch')+1:]
8459 if (pyargs != []) and (batchindex != 0):
8460 print("\n\nLuxBlend v%s - BATCH mode\n"%__version__)
8463 scene = Scene.GetCurrent()
8464 context = scene.getRenderingContext()
8465 luxUID = luxGenUID(scene)
8466 gcNamedVolumes(scene, LuxIsGUI)
8470 o, a = getopt.getopt(pyargs, 's:e:o:t:l:',["scale=","haltspp=","run=", "lbm=", "lbt="])
8476 if (opts.has_key('--run')) and (opts['--run'] == 'false'):
8478 luxProp(scene, "run", "true").set("false")
8480 luxProp(scene, "run", "true").set("true")
8482 if opts.has_key('--scale'):
8483 print("Zoom: %s" %opts['--scale'])
8484 luxProp(scene, "film.scale", "100 %").set(opts['--scale'])
8486 if opts.has_key('--haltspp'):
8487 print("haltspp: %s" %opts['--haltspp'])
8488 luxProp(scene, "haltspp", 0).set(int(opts['--haltspp']))
8490 if opts.has_key('-s'):
8491 print("Start frame: %s" %opts['-s'])
8492 context.startFrame(int(opts['-s']))
8494 print("Error: Start frame not supplied (-s)"); osys.exit(1)
8495 if opts.has_key('-e'):
8496 print("End frame: %s" %opts['-e'])
8497 context.endFrame(int(opts['-e']))
8499 print("Error: End frame not supplied (-e)")
8500 if opts.has_key('-l'):
8501 print("Path to LuxRender binary: %s" %opts['-l'])
8502 luxbatchconsolemode = luxProp(scene, "luxbatchc", "false")
8503 luxbatchconsolemode.set("true")
8504 luxpathprop = luxProp(scene, "lux", "")
8505 luxpathprop.set(opts['-l'])
8507 print("Error: path to LuxRender binary not supplied (-l)"); osys.exit(1)
8508 if opts.has_key('-o'):
8509 print("Image output path: %s" %opts['-o'])
8510 luxProp(scene, "overrideoutputpath", "").set(opts['-o'])
8512 print("Error: image output path not supplied (-o)"); osys.exit(1)
8513 if opts.has_key('-t'):
8514 print("Temporary export path: %s" %opts['-t'])
8515 luxProp(scene, "datadir", "").set(opts['-t'])
8517 print("Error: Temporary export path not supplied (-t)"); osys.exit(1)
8519 if opts.has_key('--lbm'):
8520 print("Load material: %s" %opts['--lbm'])
8521 mat = Material.Get("Material")
8522 if mat: loadMatTex(mat, opts['--lbm'])
8524 print("Error: No material with name \"Material\" found (--lbm)"); osys.exit(1)
8526 if opts.has_key('--lbt'):
8527 print("Load material: %s" %opts['--lbt'])
8528 mat = Material.Get("Material")
8529 if mat: loadMatTex(mat, opts['--lbt'], ':Kd')
8531 print("Error: No material with name \"Material\" found (--lbt)"); osys.exit(1)
8533 # CBluxAnimExport(True, True)
8534 CBluxAnimExport(True, True, False) # as by zukazuka (http://www.luxrender.net/forum/viewtopic.php?f=11&t=1288)
8538 print("\n\nLuxBlend v%s - UI mode\n"%__version__)
8539 from Blender.Window import DrawProgressBar
8541 scn = Scene.GetCurrent()
8543 Draw.Register(luxDraw, luxEvent, luxButtonEvt) # init GUI
8544 gcNamedVolumes(scn, LuxIsGUI)
8546 luxpathprop = luxProp(scn, "lux", "")
8547 luxpath = luxpathprop.get()
8548 luxrun = luxProp(scn, "run", True).get()
8549 checkluxpath = luxProp(scn, "checkluxpath", True).get()
8551 if checkluxpath and luxrun:
8552 if (luxpath is None) or (sys.exists(luxpath)<=0):
8553 # luxpath not valid, so delete entry from .blend scene file
8554 luxpathprop.delete()
8555 # and re-get luxpath, so we get the path from default-settings
8556 luxpath = luxpathprop.get()
8558 LUXRENDER_ROOT = os.getenv('LUXRENDER_ROOT')
8559 if LUXRENDER_ROOT is not None:
8560 LUXRENDER_ROOT = LUXRENDER_ROOT + os.sep
8561 luxpathprop.set(LUXRENDER_ROOT)
8562 luxpath = LUXRENDER_ROOT
8563 if sys.exists(luxpath)>0:
8564 print('LuxRender path set from LUXRENDER_ROOT environment variable')
8567 if (luxpath is None) or (sys.exists(luxpath)<=0):
8568 print("WARNING: LuxRender path \"%s\" is not valid\n"%(luxpath))
8570 r = Draw.PupMenu("Installation: Set path to the LuxRender software?%t|Yes%x1|No%x0|Never%x2")
8572 Window.FileSelector(lambda s:luxProp(scn, "lux", "").set(Blender.sys.dirname(s)+os.sep), "Select file in LuxRender path")
8575 newluxdefaults["checkluxpath"] = False
8578 print("LuxRender path check disabled\n")