2 # Copyright 2011, Blender Foundation.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 from bpy.types import Panel, Menu
25 from cycles import enums
26 from cycles import engine
29 class CYCLES_MT_integrator_presets(Menu):
30 bl_label = "Integrator Presets"
31 preset_subdir = "cycles/integrator"
32 preset_operator = "script.execute_preset"
33 COMPAT_ENGINES = {'CYCLES'}
34 draw = Menu.draw_preset
37 class CyclesButtonsPanel():
38 bl_space_type = "PROPERTIES"
39 bl_region_type = "WINDOW"
43 def poll(cls, context):
44 rd = context.scene.render
45 return rd.engine == 'CYCLES'
48 class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
49 bl_label = "Integrator"
50 bl_options = {'DEFAULT_CLOSED'}
52 def draw(self, context):
58 row = layout.row(align=True)
59 row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
60 row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
61 row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
63 split = layout.split()
66 sub = col.column(align=True)
67 sub.label(text="Samples:")
68 sub.prop(cscene, "samples", text="Render")
69 sub.prop(cscene, "preview_samples", text="Preview")
70 sub.prop(cscene, "seed")
72 sub = col.column(align=True)
73 sub.label("Transparency:")
74 sub.prop(cscene, "transparent_max_bounces", text="Max")
75 sub.prop(cscene, "transparent_min_bounces", text="Min")
76 sub.prop(cscene, "use_transparent_shadows", text="Shadows")
80 sub = col.column(align=True)
81 sub.label(text="Bounces:")
82 sub.prop(cscene, "max_bounces", text="Max")
83 sub.prop(cscene, "min_bounces", text="Min")
85 sub = col.column(align=True)
86 sub.label(text="Light Paths:")
87 sub.prop(cscene, "diffuse_bounces", text="Diffuse")
88 sub.prop(cscene, "glossy_bounces", text="Glossy")
89 sub.prop(cscene, "transmission_bounces", text="Transmission")
90 sub.prop(cscene, "no_caustics")
93 #row.prop(cscene, "blur_caustics")
94 #row.active = not cscene.no_caustics
97 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
100 def draw(self, context):
103 scene = context.scene
104 cscene = scene.cycles
106 split = layout.split()
109 col.prop(cscene, "film_exposure")
110 col.prop(cscene, "film_transparent")
113 sub = col.column(align=True)
114 sub.prop(cscene, "filter_type", text="")
115 if cscene.filter_type != 'BOX':
116 sub.prop(cscene, "filter_width", text="Width")
119 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
120 bl_label = "Performance"
121 bl_options = {'DEFAULT_CLOSED'}
123 def draw(self, context):
126 scene = context.scene
128 cscene = scene.cycles
130 split = layout.split()
132 col = split.column(align=True)
134 col.label(text="Threads:")
135 col.row().prop(rd, "threads_mode", expand=True)
137 sub.enabled = rd.threads_mode == 'FIXED'
138 sub.prop(rd, "threads")
140 sub = col.column(align=True)
141 sub.label(text="Tiles:")
142 sub.prop(cscene, "debug_tile_size")
143 sub.prop(cscene, "debug_min_size")
147 sub = col.column(align=True)
148 sub.label(text="Acceleration structure:")
149 sub.prop(cscene, "debug_bvh_type", text="")
150 sub.prop(cscene, "debug_use_spatial_splits")
153 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
155 bl_options = {'DEFAULT_CLOSED'}
156 COMPAT_ENGINES = {'BLENDER_RENDER'}
158 def draw(self, context):
161 scene = context.scene
165 # row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
167 # col = row.column(align=True)
168 # col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
169 # col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
172 # rl = rd.layers.active
175 #row.prop(rd, "use_single_layer", text="", icon_only=True)
177 split = layout.split()
180 col.prop(scene, "layers", text="Scene")
183 col.prop(rl, "layers", text="Layer")
187 layout.prop(rl, "material_override", text="Material")
190 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
191 bl_label = "Post Processing"
192 bl_options = {'DEFAULT_CLOSED'}
194 def draw(self, context):
197 rd = context.scene.render
199 split = layout.split()
202 col.prop(rd, "use_compositing")
203 col.prop(rd, "use_sequencer")
206 col.prop(rd, "dither_intensity", text="Dither", slider=True)
209 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
210 bl_label = "Depth of Field"
214 def poll(cls, context):
215 return context.camera and CyclesButtonsPanel.poll(context)
217 def draw(self, context):
223 split = layout.split()
227 col.prop(cam, "dof_object", text="")
230 sub.active = cam.dof_object is None
231 sub.prop(cam, "dof_distance", text="Distance")
235 col.label("Aperture:")
236 col.prop(ccam, "aperture_size", text="Size")
238 sub = col.column(align=True)
239 sub.prop(ccam, "aperture_blades", text="Blades")
240 sub.prop(ccam, "aperture_rotation", text="Rotation")
243 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
245 bl_context = "material"
246 bl_options = {'HIDE_HEADER'}
249 def poll(cls, context):
250 return (context.material or context.object) and CyclesButtonsPanel.poll(context)
252 def draw(self, context):
255 mat = context.material
257 slot = context.material_slot
258 space = context.space_data
263 row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
265 col = row.column(align=True)
266 col.operator("object.material_slot_add", icon='ZOOMIN', text="")
267 col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
269 col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
271 if ob.mode == 'EDIT':
272 row = layout.row(align=True)
273 row.operator("object.material_slot_assign", text="Assign")
274 row.operator("object.material_slot_select", text="Select")
275 row.operator("object.material_slot_deselect", text="Deselect")
277 split = layout.split(percentage=0.65)
280 split.template_ID(ob, "active_material", new="material.new")
284 row.prop(slot, "link", text="")
288 split.template_ID(space, "pin_id")
292 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
293 bl_label = "Displacement"
297 def poll(cls, context):
298 return CyclesButtonsPanel.poll(context) and context.mesh or context.curve or context.meta_ball
300 def draw(self, context):
304 curve = context.curve
305 mball = context.meta_ball
314 layout.prop(cdata, "displacement_method", text="Method")
315 layout.prop(cdata, "use_subdivision")
316 layout.prop(cdata, "dicing_rate")
319 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
320 bl_label = "Ray Visibility"
321 bl_context = "object"
322 bl_options = {'DEFAULT_CLOSED'}
325 def poll(cls, context):
327 return CyclesButtonsPanel.poll(context) and ob and ob.type in ('MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META') # todo: 'LAMP'
329 def draw(self, context):
333 visibility = ob.cycles_visibility
335 split = layout.split()
338 col.prop(visibility, "camera")
339 col.prop(visibility, "diffuse")
340 col.prop(visibility, "glossy")
343 col.prop(visibility, "transmission")
344 col.prop(visibility, "shadow")
347 def find_node(material, nodetype):
348 if material and material.node_tree:
349 ntree = material.node_tree
351 for node in ntree.nodes:
352 if hasattr(node, 'type') and node.type == nodetype:
358 def find_node_input(node, name):
359 for input in node.inputs:
360 if input.name == name:
366 def panel_node_draw(layout, id, output_type, input_name):
368 layout.prop(id, "use_nodes", icon='NODETREE')
373 node = find_node(id, output_type)
375 layout.label(text="No output node.")
377 input = find_node_input(node, input_name)
378 layout.template_node_view(ntree, node, input)
383 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
388 def poll(cls, context):
389 return context.lamp and CyclesButtonsPanel.poll(context)
391 def draw(self, context):
397 layout.prop(lamp, "type", expand=True)
399 split = layout.split()
400 col = split.column(align=True)
402 if lamp.type in ('POINT', 'SUN', 'SPOT'):
403 col.prop(lamp, "shadow_soft_size", text="Size")
404 elif lamp.type == 'AREA':
405 col.prop(lamp, "shape", text="")
406 sub = col.column(align=True)
408 if lamp.shape == 'SQUARE':
409 sub.prop(lamp, "size")
410 elif lamp.shape == 'RECTANGLE':
411 sub.prop(lamp, "size", text="Size X")
412 sub.prop(lamp, "size_y", text="Size Y")
415 col.prop(clamp, "cast_shadow")
417 if lamp.type == 'SPOT':
418 layout.label(text="Not supported, interpreted as point lamp.")
419 elif lamp.type == 'HEMI':
420 layout.label(text="Not supported, interpreted as sun lamp.")
423 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
428 def poll(cls, context):
429 return context.lamp and CyclesButtonsPanel.poll(context)
431 def draw(self, context):
435 if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
436 layout.prop(lamp, "color")
439 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
444 def poll(cls, context):
445 return context.world and CyclesButtonsPanel.poll(context)
447 def draw(self, context):
450 world = context.world
451 if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
452 layout.prop(world, "horizon_color", text="Color")
455 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
458 bl_options = {'DEFAULT_CLOSED'}
461 def poll(cls, context):
462 world = context.world
463 return False # world and world.node_tree and CyclesButtonsPanel.poll(context)
465 def draw(self, context):
467 layout.active = False
469 world = context.world
470 panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
473 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
475 bl_context = "material"
478 def poll(cls, context):
479 return context.material and CyclesButtonsPanel.poll(context)
481 def draw(self, context):
484 mat = context.material
485 if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
486 layout.prop(mat, "diffuse_color")
489 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
491 bl_context = "material"
492 bl_options = {'DEFAULT_CLOSED'}
495 def poll(cls, context):
496 mat = context.material
497 return False # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
499 def draw(self, context):
501 layout.active = False
503 mat = context.material
506 panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
508 layout.prop(cmat, "homogeneous_volume")
511 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
512 bl_label = "Displacement"
513 bl_context = "material"
516 def poll(cls, context):
517 mat = context.material
518 return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
520 def draw(self, context):
523 mat = context.material
524 panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
527 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
528 bl_label = "Settings"
529 bl_context = "material"
530 bl_options = {'DEFAULT_CLOSED'}
533 def poll(cls, context):
534 return context.material and CyclesButtonsPanel.poll(context)
536 def draw(self, context):
539 mat = context.material
542 split = layout.split()
545 col.prop(mat, "diffuse_color", text="Viewport Color")
548 col.prop(cmat, "sample_as_light")
551 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
553 bl_context = "texture"
554 bl_options = {'HIDE_HEADER'}
555 COMPAT_ENGINES = {'CYCLES'}
557 def draw(self, context):
560 tex = context.texture
561 space = context.space_data
562 pin_id = space.pin_id
563 use_pin_id = space.use_pin_id
564 user = context.texture_user
565 node = context.texture_node
567 if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
571 layout.template_texture_user()
576 split = layout.split(percentage=0.65)
580 col.template_ID(space, "pin_id")
582 col.template_ID(user, "texture", new="texture.new")
586 row.prop(tex, "use_nodes", icon="NODETREE", text="")
589 if not tex.use_nodes:
590 split = layout.split(percentage=0.2)
591 split.label(text="Type:")
592 split.prop(tex, "type", text="")
595 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
597 bl_context = "texture"
600 def poll(cls, context):
601 tex = context.texture
602 return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
604 def draw(self, context):
607 tex = context.texture
608 panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
611 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
613 bl_context = "texture"
616 def poll(cls, context):
617 node = context.texture_node
618 return node and CyclesButtonsPanel.poll(context)
620 def draw(self, context):
623 node = context.texture_node
625 layout.template_node_view(ntree, node, None)
628 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
630 bl_context = "texture"
633 def poll(cls, context):
634 tex = context.texture
635 node = context.texture_node
636 return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
638 def draw(self, context):
641 tex = context.texture
642 node = context.texture_node
644 mapping = node.texture_mapping
648 row.column().prop(mapping, "location")
649 row.column().prop(mapping, "rotation")
650 row.column().prop(mapping, "scale")
652 layout.label(text="Projection:")
655 row.prop(mapping, "mapping_x", text="")
656 row.prop(mapping, "mapping_y", text="")
657 row.prop(mapping, "mapping_z", text="")
660 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
662 bl_context = "texture"
663 bl_options = {'DEFAULT_CLOSED'}
666 def poll(cls, context):
667 tex = context.texture
668 node = context.texture_node
670 #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
672 def draw(self, context):
675 tex = context.texture
676 node = context.texture_node
678 mapping = node.color_mapping
680 split = layout.split()
683 col.label(text="Blend:")
684 col.prop(mapping, "blend_type", text="")
685 col.prop(mapping, "blend_factor", text="Factor")
686 col.prop(mapping, "blend_color", text="")
689 col.label(text="Adjust:")
690 col.prop(mapping, "brightness")
691 col.prop(mapping, "contrast")
692 col.prop(mapping, "saturation")
696 layout.prop(mapping, "use_color_ramp", text="Ramp")
697 if mapping.use_color_ramp:
698 layout.template_color_ramp(mapping, "color_ramp", expand=True)
701 def draw_device(self, context):
702 scene = context.scene
705 if scene.render.engine == "CYCLES":
706 cscene = scene.cycles
708 available_devices = engine.available_devices()
709 available_cuda = 'cuda' in available_devices
710 available_opencl = 'opencl' in available_devices
712 if available_cuda or available_opencl:
713 layout.prop(cscene, "device")
714 if cscene.device == 'GPU' and available_cuda and available_opencl:
715 layout.prop(cscene, "gpu_type")
716 if cscene.device == 'CPU' and engine.with_osl():
717 layout.prop(cscene, "shading_system")
720 def draw_pause(self, context):
722 scene = context.scene
724 if scene.render.engine == "CYCLES":
725 view = context.space_data
727 if view.viewport_shade == "RENDERED":
728 cscene = scene.cycles
729 layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
734 bpy.types.RENDER_PT_render,
735 bpy.types.RENDER_PT_output,
736 bpy.types.RENDER_PT_encoding,
737 bpy.types.RENDER_PT_dimensions,
738 bpy.types.RENDER_PT_stamp,
739 bpy.types.WORLD_PT_context_world,
740 bpy.types.DATA_PT_context_mesh,
741 bpy.types.DATA_PT_context_camera,
742 bpy.types.DATA_PT_context_lamp,
743 bpy.types.DATA_PT_texture_space,
744 bpy.types.DATA_PT_curve_texture_space,
745 bpy.types.DATA_PT_mball_texture_space,
746 bpy.types.DATA_PT_vertex_groups,
747 bpy.types.DATA_PT_shape_keys,
748 bpy.types.DATA_PT_uv_texture,
749 bpy.types.DATA_PT_vertex_colors,
750 bpy.types.DATA_PT_camera,
751 bpy.types.DATA_PT_camera_display,
752 bpy.types.DATA_PT_lens,
753 bpy.types.DATA_PT_custom_props_mesh,
754 bpy.types.DATA_PT_custom_props_camera,
755 bpy.types.DATA_PT_custom_props_lamp,
756 bpy.types.TEXTURE_PT_clouds,
757 bpy.types.TEXTURE_PT_wood,
758 bpy.types.TEXTURE_PT_marble,
759 bpy.types.TEXTURE_PT_magic,
760 bpy.types.TEXTURE_PT_blend,
761 bpy.types.TEXTURE_PT_stucci,
762 bpy.types.TEXTURE_PT_image,
763 bpy.types.TEXTURE_PT_image_sampling,
764 bpy.types.TEXTURE_PT_image_mapping,
765 bpy.types.TEXTURE_PT_musgrave,
766 bpy.types.TEXTURE_PT_voronoi,
767 bpy.types.TEXTURE_PT_distortednoise,
768 bpy.types.TEXTURE_PT_voxeldata,
769 bpy.types.TEXTURE_PT_pointdensity,
770 bpy.types.TEXTURE_PT_pointdensity_turbulence,
771 bpy.types.PARTICLE_PT_context_particles,
772 bpy.types.PARTICLE_PT_emission,
773 bpy.types.PARTICLE_PT_hair_dynamics,
774 bpy.types.PARTICLE_PT_cache,
775 bpy.types.PARTICLE_PT_velocity,
776 bpy.types.PARTICLE_PT_rotation,
777 bpy.types.PARTICLE_PT_physics,
778 bpy.types.PARTICLE_PT_boidbrain,
779 bpy.types.PARTICLE_PT_render,
780 bpy.types.PARTICLE_PT_draw,
781 bpy.types.PARTICLE_PT_children,
782 bpy.types.PARTICLE_PT_field_weights,
783 bpy.types.PARTICLE_PT_force_fields,
784 bpy.types.PARTICLE_PT_vertexgroups,
785 bpy.types.PARTICLE_PT_custom_props]
789 bpy.types.RENDER_PT_render.append(draw_device)
790 bpy.types.VIEW3D_HT_header.append(draw_pause)
792 for panel in get_panels():
793 panel.COMPAT_ENGINES.add('CYCLES')
797 bpy.types.RENDER_PT_render.remove(draw_device)
798 bpy.types.VIEW3D_HT_header.remove(draw_pause)
800 for panel in get_panels():
801 panel.COMPAT_ENGINES.remove('CYCLES')