Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / blender / addon / ui.py
1 #
2 # Copyright 2011-2013 Blender Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # <pep8 compliant>
18
19 import bpy
20
21 from bpy.types import (
22         Panel,
23         Menu,
24         Operator,
25         )
26
27
28 class CYCLES_MT_sampling_presets(Menu):
29     bl_label = "Sampling Presets"
30     preset_subdir = "cycles/sampling"
31     preset_operator = "script.execute_preset"
32     COMPAT_ENGINES = {'CYCLES'}
33     draw = Menu.draw_preset
34
35
36 class CYCLES_MT_integrator_presets(Menu):
37     bl_label = "Integrator Presets"
38     preset_subdir = "cycles/integrator"
39     preset_operator = "script.execute_preset"
40     COMPAT_ENGINES = {'CYCLES'}
41     draw = Menu.draw_preset
42
43
44 class CyclesButtonsPanel:
45     bl_space_type = "PROPERTIES"
46     bl_region_type = "WINDOW"
47     bl_context = "render"
48     COMPAT_ENGINES = {'CYCLES'}
49
50     @classmethod
51     def poll(cls, context):
52         rd = context.scene.render
53         return rd.engine in cls.COMPAT_ENGINES
54
55
56 def get_device_type(context):
57     return context.user_preferences.addons[__package__].preferences.compute_device_type
58
59
60 def use_cpu(context):
61     cscene = context.scene.cycles
62
63     return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
64
65
66 def use_opencl(context):
67     cscene = context.scene.cycles
68
69     return (get_device_type(context) == 'OPENCL' and cscene.device == 'GPU')
70
71
72 def use_cuda(context):
73     cscene = context.scene.cycles
74
75     return (get_device_type(context) == 'CUDA' and cscene.device == 'GPU')
76
77
78 def use_branched_path(context):
79     cscene = context.scene.cycles
80
81     return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
82
83
84 def use_sample_all_lights(context):
85     cscene = context.scene.cycles
86
87     return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
88
89 def show_device_active(context):
90     cscene = context.scene.cycles
91     if cscene.device != 'GPU':
92         return True
93     return context.user_preferences.addons[__package__].preferences.has_active_device()
94
95
96 def draw_samples_info(layout, context):
97     cscene = context.scene.cycles
98     integrator = cscene.progressive
99
100     # Calculate sample values
101     if integrator == 'PATH':
102         aa = cscene.samples
103         if cscene.use_square_samples:
104             aa = aa * aa
105     else:
106         aa = cscene.aa_samples
107         d = cscene.diffuse_samples
108         g = cscene.glossy_samples
109         t = cscene.transmission_samples
110         ao = cscene.ao_samples
111         ml = cscene.mesh_light_samples
112         sss = cscene.subsurface_samples
113         vol = cscene.volume_samples
114
115         if cscene.use_square_samples:
116             aa = aa * aa
117             d = d * d
118             g = g * g
119             t = t * t
120             ao = ao * ao
121             ml = ml * ml
122             sss = sss * sss
123             vol = vol * vol
124
125     # Draw interface
126     # Do not draw for progressive, when Square Samples are disabled
127     if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
128         col = layout.column(align=True)
129         col.scale_y = 0.6
130         col.label("Total Samples:")
131         col.separator()
132         if integrator == 'PATH':
133             col.label("%s AA" % aa)
134         else:
135             col.label("%s AA, %s Diffuse, %s Glossy, %s Transmission" %
136                       (aa, d * aa, g * aa, t * aa))
137             col.separator()
138             col.label("%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
139                       (ao * aa, ml * aa, sss * aa, vol * aa))
140
141
142 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
143     bl_label = "Sampling"
144     bl_options = {'DEFAULT_CLOSED'}
145
146     def draw(self, context):
147         layout = self.layout
148
149         scene = context.scene
150         cscene = scene.cycles
151
152         row = layout.row(align=True)
153         row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
154         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
155         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
156
157         row = layout.row()
158         sub = row.row()
159         sub.active = get_device_type(context) != 'OPENCL' or use_cpu(context)
160         sub.prop(cscene, "progressive", text="")
161         row.prop(cscene, "use_square_samples")
162
163         split = layout.split()
164
165         col = split.column()
166         sub = col.column(align=True)
167         sub.label("Settings:")
168
169         seed_sub = sub.row(align=True)
170         seed_sub.prop(cscene, "seed")
171         seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
172
173         sub.prop(cscene, "sample_clamp_direct")
174         sub.prop(cscene, "sample_clamp_indirect")
175         sub.prop(cscene, "light_sampling_threshold")
176
177         if cscene.progressive == 'PATH' or use_branched_path(context) is False:
178             col = split.column()
179             sub = col.column(align=True)
180             sub.label(text="Samples:")
181             sub.prop(cscene, "samples", text="Render")
182             sub.prop(cscene, "preview_samples", text="Preview")
183         else:
184             sub.label(text="AA Samples:")
185             sub.prop(cscene, "aa_samples", text="Render")
186             sub.prop(cscene, "preview_aa_samples", text="Preview")
187             sub.separator()
188             sub.prop(cscene, "sample_all_lights_direct")
189             sub.prop(cscene, "sample_all_lights_indirect")
190
191             col = split.column()
192             sub = col.column(align=True)
193             sub.label(text="Samples:")
194             sub.prop(cscene, "diffuse_samples", text="Diffuse")
195             sub.prop(cscene, "glossy_samples", text="Glossy")
196             sub.prop(cscene, "transmission_samples", text="Transmission")
197             sub.prop(cscene, "ao_samples", text="AO")
198
199             subsub = sub.row(align=True)
200             subsub.active = use_sample_all_lights(context)
201             subsub.prop(cscene, "mesh_light_samples", text="Mesh Light")
202
203             sub.prop(cscene, "subsurface_samples", text="Subsurface")
204             sub.prop(cscene, "volume_samples", text="Volume")
205
206         if not (use_opencl(context) and cscene.feature_set != 'EXPERIMENTAL'):
207             layout.row().prop(cscene, "sampling_pattern", text="Pattern")
208
209         for rl in scene.render.layers:
210             if rl.samples > 0:
211                 layout.separator()
212                 layout.row().prop(cscene, "use_layer_samples")
213                 break
214
215         draw_samples_info(layout, context)
216
217
218 class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel):
219     bl_label = "Geometry"
220     bl_options = {'DEFAULT_CLOSED'}
221
222     def draw(self, context):
223         layout = self.layout
224
225         scene = context.scene
226         cscene = scene.cycles
227         ccscene = scene.cycles_curves
228
229         if cscene.feature_set == 'EXPERIMENTAL':
230             split = layout.split()
231
232             col = split.column()
233
234             sub = col.column(align=True)
235             sub.label("Volume Sampling:")
236             sub.prop(cscene, "volume_step_size")
237             sub.prop(cscene, "volume_max_steps")
238
239             col = split.column()
240
241             sub = col.column(align=True)
242             sub.label("Subdivision Rate:")
243             sub.prop(cscene, "dicing_rate", text="Render")
244             sub.prop(cscene, "preview_dicing_rate", text="Preview")
245             sub.separator()
246             sub.prop(cscene, "max_subdivisions")
247         else:
248             row = layout.row()
249             row.label("Volume Sampling:")
250             row = layout.row()
251             row.prop(cscene, "volume_step_size")
252             row.prop(cscene, "volume_max_steps")
253
254         layout.prop(ccscene, "use_curves", text="Use Hair")
255         col = layout.column()
256         col.active = ccscene.use_curves
257
258         col.prop(ccscene, "primitive", text="Primitive")
259         col.prop(ccscene, "shape", text="Shape")
260
261         if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
262             col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
263
264         if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
265             col.prop(ccscene, "resolution", text="Resolution")
266         elif ccscene.primitive == 'CURVE_SEGMENTS':
267             col.prop(ccscene, "subdivisions", text="Curve subdivisions")
268
269         row = col.row()
270         row.prop(ccscene, "minimum_width", text="Min Pixels")
271         row.prop(ccscene, "maximum_width", text="Max Ext.")
272
273
274 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
275     bl_label = "Light Paths"
276     bl_options = {'DEFAULT_CLOSED'}
277
278     def draw(self, context):
279         layout = self.layout
280
281         scene = context.scene
282         cscene = scene.cycles
283
284         row = layout.row(align=True)
285         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
286         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
287         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
288
289         split = layout.split()
290
291         col = split.column()
292
293         sub = col.column(align=True)
294         sub.label("Transparency:")
295         sub.prop(cscene, "transparent_max_bounces", text="Max")
296         sub.prop(cscene, "transparent_min_bounces", text="Min")
297         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
298
299         col.separator()
300
301         col.prop(cscene, "caustics_reflective")
302         col.prop(cscene, "caustics_refractive")
303         col.prop(cscene, "blur_glossy")
304
305         col = split.column()
306
307         sub = col.column(align=True)
308         sub.label(text="Bounces:")
309         sub.prop(cscene, "max_bounces", text="Max")
310         sub.prop(cscene, "min_bounces", text="Min")
311
312         sub = col.column(align=True)
313         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
314         sub.prop(cscene, "glossy_bounces", text="Glossy")
315         sub.prop(cscene, "transmission_bounces", text="Transmission")
316         sub.prop(cscene, "volume_bounces", text="Volume")
317
318
319 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
320     bl_label = "Motion Blur"
321     bl_options = {'DEFAULT_CLOSED'}
322
323     def draw_header(self, context):
324         rd = context.scene.render
325
326         self.layout.prop(rd, "use_motion_blur", text="")
327
328     def draw(self, context):
329         layout = self.layout
330
331         scene = context.scene
332         cscene = scene.cycles
333         rd = scene.render
334         layout.active = rd.use_motion_blur
335
336         col = layout.column()
337         col.prop(cscene, "motion_blur_position", text="Position")
338         col.prop(rd, "motion_blur_shutter")
339
340         col = layout.column()
341         col.label("Shutter curve:")
342         col.template_curve_mapping(rd, "motion_blur_shutter_curve")
343
344         col = layout.column(align=True)
345         row = col.row(align=True)
346         row.operator("render.shutter_curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
347         row.operator("render.shutter_curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
348         row.operator("render.shutter_curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
349         row.operator("render.shutter_curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
350         row.operator("render.shutter_curve_preset", icon='LINCURVE', text="").shape = 'LINE'
351         row.operator("render.shutter_curve_preset", icon='NOCURVE', text="").shape = 'MAX'
352
353         col = layout.column()
354         col.prop(cscene, "rolling_shutter_type")
355         row = col.row()
356         row.active = cscene.rolling_shutter_type != 'NONE'
357         row.prop(cscene, "rolling_shutter_duration")
358
359
360 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
361     bl_label = "Film"
362
363     def draw(self, context):
364         layout = self.layout
365
366         scene = context.scene
367         cscene = scene.cycles
368
369         split = layout.split()
370
371         col = split.column()
372         col.prop(cscene, "film_exposure")
373         col.prop(cscene, "film_transparent")
374
375         col = split.column()
376         sub = col.column(align=True)
377         sub.prop(cscene, "pixel_filter_type", text="")
378         if cscene.pixel_filter_type != 'BOX':
379             sub.prop(cscene, "filter_width", text="Width")
380
381
382 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
383     bl_label = "Performance"
384     bl_options = {'DEFAULT_CLOSED'}
385
386     def draw(self, context):
387         layout = self.layout
388
389         scene = context.scene
390         rd = scene.render
391         cscene = scene.cycles
392
393         split = layout.split()
394
395         col = split.column(align=True)
396
397         col.label(text="Threads:")
398         col.row(align=True).prop(rd, "threads_mode", expand=True)
399         sub = col.column(align=True)
400         sub.enabled = rd.threads_mode == 'FIXED'
401         sub.prop(rd, "threads")
402
403         sub = col.column(align=True)
404         sub.label(text="Tiles:")
405         sub.prop(cscene, "tile_order", text="")
406
407         sub.prop(rd, "tile_x", text="X")
408         sub.prop(rd, "tile_y", text="Y")
409
410         sub.prop(cscene, "use_progressive_refine")
411
412         subsub = sub.column(align=True)
413         subsub.prop(rd, "use_save_buffers")
414
415         col = split.column(align=True)
416
417         col.label(text="Viewport:")
418         col.prop(cscene, "debug_bvh_type", text="")
419         col.separator()
420         col.prop(cscene, "preview_start_resolution")
421
422         col.separator()
423
424         col.label(text="Final Render:")
425         col.prop(rd, "use_persistent_data", text="Persistent Images")
426
427         col.separator()
428
429         col.label(text="Acceleration structure:")
430         col.prop(cscene, "debug_use_spatial_splits")
431         col.prop(cscene, "debug_use_hair_bvh")
432
433         row = col.row()
434         row.active = not cscene.debug_use_spatial_splits
435         row.prop(cscene, "debug_bvh_time_steps")
436
437
438 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
439     bl_label = "Layer"
440     bl_context = "render_layer"
441
442     def draw(self, context):
443         layout = self.layout
444
445         scene = context.scene
446         rd = scene.render
447         rl = rd.layers.active
448
449         split = layout.split()
450
451         col = split.column()
452         col.prop(scene, "layers", text="Scene")
453         col.prop(rl, "layers_exclude", text="Exclude")
454
455         col = split.column()
456         col.prop(rl, "layers", text="Layer")
457         col.prop(rl, "layers_zmask", text="Mask Layer")
458
459         split = layout.split()
460
461         col = split.column()
462         col.label(text="Material:")
463         col.prop(rl, "material_override", text="")
464         col.separator()
465         col.prop(rl, "samples")
466
467         col = split.column()
468         col.prop(rl, "use_sky", "Use Environment")
469         col.prop(rl, "use_ao", "Use AO")
470         col.prop(rl, "use_solid", "Use Surfaces")
471         col.prop(rl, "use_strand", "Use Hair")
472
473
474 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
475     bl_label = "Passes"
476     bl_context = "render_layer"
477     bl_options = {'DEFAULT_CLOSED'}
478
479     def draw(self, context):
480         layout = self.layout
481
482         scene = context.scene
483         rd = scene.render
484         rl = rd.layers.active
485
486         split = layout.split()
487
488         col = split.column()
489         col.prop(rl, "use_pass_combined")
490         col.prop(rl, "use_pass_z")
491         col.prop(rl, "use_pass_mist")
492         col.prop(rl, "use_pass_normal")
493         row = col.row()
494         row.prop(rl, "use_pass_vector")
495         row.active = not rd.use_motion_blur
496         col.prop(rl, "use_pass_uv")
497         col.prop(rl, "use_pass_object_index")
498         col.prop(rl, "use_pass_material_index")
499         col.separator()
500         col.prop(rl, "use_pass_shadow")
501         col.prop(rl, "use_pass_ambient_occlusion")
502         col.separator()
503         col.prop(rl, "pass_alpha_threshold")
504
505         col = split.column()
506         col.label(text="Diffuse:")
507         row = col.row(align=True)
508         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
509         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
510         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
511         col.label(text="Glossy:")
512         row = col.row(align=True)
513         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
514         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
515         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
516         col.label(text="Transmission:")
517         row = col.row(align=True)
518         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
519         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
520         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
521         col.label(text="Subsurface:")
522         row = col.row(align=True)
523         row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
524         row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
525         row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
526
527         col.separator()
528         col.prop(rl, "use_pass_emit", text="Emission")
529         col.prop(rl, "use_pass_environment")
530
531         if hasattr(rd, "debug_pass_type"):
532             layout.prop(rd, "debug_pass_type")
533
534
535 class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
536     bl_label = "Views"
537     bl_context = "render_layer"
538     bl_options = {'DEFAULT_CLOSED'}
539
540     def draw_header(self, context):
541         rd = context.scene.render
542         self.layout.prop(rd, "use_multiview", text="")
543
544     def draw(self, context):
545         layout = self.layout
546
547         scene = context.scene
548         rd = scene.render
549         rv = rd.views.active
550
551         layout.active = rd.use_multiview
552         basic_stereo = (rd.views_format == 'STEREO_3D')
553
554         row = layout.row()
555         row.prop(rd, "views_format", expand=True)
556
557         if basic_stereo:
558             row = layout.row()
559             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
560
561             row = layout.row()
562             row.label(text="File Suffix:")
563             row.prop(rv, "file_suffix", text="")
564
565         else:
566             row = layout.row()
567             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
568
569             col = row.column(align=True)
570             col.operator("scene.render_view_add", icon='ZOOMIN', text="")
571             col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
572
573             row = layout.row()
574             row.label(text="Camera Suffix:")
575             row.prop(rv, "camera_suffix", text="")
576
577
578 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
579     bl_label = "Post Processing"
580     bl_options = {'DEFAULT_CLOSED'}
581
582     def draw(self, context):
583         layout = self.layout
584
585         rd = context.scene.render
586
587         split = layout.split()
588
589         col = split.column()
590         col.prop(rd, "use_compositing")
591         col.prop(rd, "use_sequencer")
592
593         col = split.column()
594         col.prop(rd, "dither_intensity", text="Dither", slider=True)
595
596
597 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
598     bl_label = "Depth of Field"
599     bl_context = "data"
600
601     @classmethod
602     def poll(cls, context):
603         return context.camera and CyclesButtonsPanel.poll(context)
604
605     def draw(self, context):
606         layout = self.layout
607
608         cam = context.camera
609         ccam = cam.cycles
610         dof_options = cam.gpu_dof
611
612         split = layout.split()
613
614         col = split.column()
615         col.label("Focus:")
616         col.prop(cam, "dof_object", text="")
617
618         sub = col.row()
619         sub.active = cam.dof_object is None
620         sub.prop(cam, "dof_distance", text="Distance")
621
622         hq_support = dof_options.is_hq_supported
623         sub = col.column(align=True)
624         sub.label("Viewport:")
625         subhq = sub.column()
626         subhq.active = hq_support
627         subhq.prop(dof_options, "use_high_quality")
628         sub.prop(dof_options, "fstop")
629         if dof_options.use_high_quality and hq_support:
630             sub.prop(dof_options, "blades")
631
632         col = split.column()
633
634         col.label("Aperture:")
635         sub = col.column(align=True)
636         sub.prop(ccam, "aperture_type", text="")
637         if ccam.aperture_type == 'RADIUS':
638             sub.prop(ccam, "aperture_size", text="Size")
639         elif ccam.aperture_type == 'FSTOP':
640             sub.prop(ccam, "aperture_fstop", text="Number")
641
642         sub = col.column(align=True)
643         sub.prop(ccam, "aperture_blades", text="Blades")
644         sub.prop(ccam, "aperture_rotation", text="Rotation")
645         sub.prop(ccam, "aperture_ratio", text="Ratio")
646
647
648 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
649     bl_label = ""
650     bl_context = "material"
651     bl_options = {'HIDE_HEADER'}
652
653     @classmethod
654     def poll(cls, context):
655         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
656
657     def draw(self, context):
658         layout = self.layout
659
660         mat = context.material
661         ob = context.object
662         slot = context.material_slot
663         space = context.space_data
664
665         if ob:
666             is_sortable = len(ob.material_slots) > 1
667             rows = 1
668             if (is_sortable):
669                 rows = 4
670
671             row = layout.row()
672
673             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
674
675             col = row.column(align=True)
676             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
677             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
678
679             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
680
681             if is_sortable:
682                 col.separator()
683
684                 col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
685                 col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
686
687             if ob.mode == 'EDIT':
688                 row = layout.row(align=True)
689                 row.operator("object.material_slot_assign", text="Assign")
690                 row.operator("object.material_slot_select", text="Select")
691                 row.operator("object.material_slot_deselect", text="Deselect")
692
693         split = layout.split(percentage=0.65)
694
695         if ob:
696             split.template_ID(ob, "active_material", new="material.new")
697             row = split.row()
698
699             if slot:
700                 row.prop(slot, "link", text="")
701             else:
702                 row.label()
703         elif mat:
704             split.template_ID(space, "pin_id")
705             split.separator()
706
707
708 class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
709     bl_label = "Motion Blur"
710     bl_context = "object"
711     bl_options = {'DEFAULT_CLOSED'}
712
713     @classmethod
714     def poll(cls, context):
715         ob = context.object
716         if CyclesButtonsPanel.poll(context) and ob:
717             if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
718                 return True
719             if ob.dupli_type == 'GROUP' and ob.dupli_group:
720                 return True
721             # TODO(sergey): More duplicator types here?
722         return False
723
724     def draw_header(self, context):
725         layout = self.layout
726
727         rd = context.scene.render
728         # scene = context.scene
729
730         layout.active = rd.use_motion_blur
731
732         ob = context.object
733         cob = ob.cycles
734
735         layout.prop(cob, "use_motion_blur", text="")
736
737     def draw(self, context):
738         layout = self.layout
739
740         rd = context.scene.render
741         # scene = context.scene
742
743         ob = context.object
744         cob = ob.cycles
745
746         layout.active = (rd.use_motion_blur and cob.use_motion_blur)
747
748         row = layout.row()
749         row.prop(cob, "use_deform_motion", text="Deformation")
750
751         sub = row.row()
752         sub.active = cob.use_deform_motion
753         sub.prop(cob, "motion_steps", text="Steps")
754
755
756 class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
757     bl_label = "Cycles Settings"
758     bl_context = "object"
759     bl_options = {'DEFAULT_CLOSED'}
760
761     @classmethod
762     def poll(cls, context):
763         ob = context.object
764         return (CyclesButtonsPanel.poll(context) and
765                 ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
766                         (ob.dupli_type == 'GROUP' and ob.dupli_group)))
767
768     def draw(self, context):
769         layout = self.layout
770
771         scene = context.scene
772         cscene = scene.cycles
773         ob = context.object
774         cob = ob.cycles
775         visibility = ob.cycles_visibility
776
777         layout.label(text="Ray Visibility:")
778         flow = layout.column_flow()
779
780         flow.prop(visibility, "camera")
781         flow.prop(visibility, "diffuse")
782         flow.prop(visibility, "glossy")
783         flow.prop(visibility, "transmission")
784         flow.prop(visibility, "scatter")
785
786         if ob.type != 'LAMP':
787             flow.prop(visibility, "shadow")
788
789         col = layout.column()
790         col.label(text="Performance:")
791         row = col.row()
792         sub = row.row()
793         sub.active = scene.render.use_simplify and cscene.use_camera_cull
794         sub.prop(cob, "use_camera_cull")
795
796         sub = row.row()
797         sub.active = scene.render.use_simplify and cscene.use_distance_cull
798         sub.prop(cob, "use_distance_cull")
799
800
801 class CYCLES_OT_use_shading_nodes(Operator):
802     """Enable nodes on a material, world or lamp"""
803     bl_idname = "cycles.use_shading_nodes"
804     bl_label = "Use Nodes"
805
806     @classmethod
807     def poll(cls, context):
808         return (getattr(context, "material", False) or getattr(context, "world", False) or
809                 getattr(context, "lamp", False))
810
811     def execute(self, context):
812         if context.material:
813             context.material.use_nodes = True
814         elif context.world:
815             context.world.use_nodes = True
816         elif context.lamp:
817             context.lamp.use_nodes = True
818
819         return {'FINISHED'}
820
821
822 def find_node(material, nodetype):
823     if material and material.node_tree:
824         ntree = material.node_tree
825
826         active_output_node = None
827         for node in ntree.nodes:
828             if getattr(node, "type", None) == nodetype:
829                 if getattr(node, "is_active_output", True):
830                     return node
831                 if not active_output_node:
832                     active_output_node = node
833         return active_output_node
834
835     return None
836
837
838 def find_node_input(node, name):
839     for input in node.inputs:
840         if input.name == name:
841             return input
842
843     return None
844
845
846 def panel_node_draw(layout, id_data, output_type, input_name):
847     if not id_data.use_nodes:
848         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
849         return False
850
851     ntree = id_data.node_tree
852
853     node = find_node(id_data, output_type)
854     if not node:
855         layout.label(text="No output node")
856     else:
857         input = find_node_input(node, input_name)
858         layout.template_node_view(ntree, node, input)
859
860     return True
861
862
863 class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
864     bl_label = "Preview"
865     bl_context = "data"
866     bl_options = {'DEFAULT_CLOSED'}
867
868     @classmethod
869     def poll(cls, context):
870         return context.lamp and \
871                not (context.lamp.type == 'AREA' and
872                     context.lamp.cycles.is_portal) \
873                and CyclesButtonsPanel.poll(context)
874
875     def draw(self, context):
876         self.layout.template_preview(context.lamp)
877
878
879 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
880     bl_label = "Lamp"
881     bl_context = "data"
882
883     @classmethod
884     def poll(cls, context):
885         return context.lamp and CyclesButtonsPanel.poll(context)
886
887     def draw(self, context):
888         layout = self.layout
889
890         lamp = context.lamp
891         clamp = lamp.cycles
892         # cscene = context.scene.cycles
893
894         layout.prop(lamp, "type", expand=True)
895
896         split = layout.split()
897         col = split.column(align=True)
898
899         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
900             col.prop(lamp, "shadow_soft_size", text="Size")
901         elif lamp.type == 'AREA':
902             col.prop(lamp, "shape", text="")
903             sub = col.column(align=True)
904
905             if lamp.shape == 'SQUARE':
906                 sub.prop(lamp, "size")
907             elif lamp.shape == 'RECTANGLE':
908                 sub.prop(lamp, "size", text="Size X")
909                 sub.prop(lamp, "size_y", text="Size Y")
910
911         if not (lamp.type == 'AREA' and clamp.is_portal):
912             sub = col.column(align=True)
913             if use_branched_path(context):
914                 subsub = sub.row(align=True)
915                 subsub.active = use_sample_all_lights(context)
916                 subsub.prop(clamp, "samples")
917             sub.prop(clamp, "max_bounces")
918
919         col = split.column()
920
921         sub = col.column(align=True)
922         sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
923         sub.prop(clamp, "cast_shadow")
924         sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
925
926         if lamp.type == 'AREA':
927             col.prop(clamp, "is_portal", text="Portal")
928
929         if lamp.type == 'HEMI':
930             layout.label(text="Not supported, interpreted as sun lamp")
931
932
933 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
934     bl_label = "Nodes"
935     bl_context = "data"
936
937     @classmethod
938     def poll(cls, context):
939         return context.lamp and not (context.lamp.type == 'AREA' and
940                                      context.lamp.cycles.is_portal) and \
941                CyclesButtonsPanel.poll(context)
942
943     def draw(self, context):
944         layout = self.layout
945
946         lamp = context.lamp
947         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
948             layout.prop(lamp, "color")
949
950
951 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
952     bl_label = "Spot Shape"
953     bl_context = "data"
954
955     @classmethod
956     def poll(cls, context):
957         lamp = context.lamp
958         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
959
960     def draw(self, context):
961         layout = self.layout
962
963         lamp = context.lamp
964
965         split = layout.split()
966
967         col = split.column()
968         sub = col.column()
969         sub.prop(lamp, "spot_size", text="Size")
970         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
971
972         col = split.column()
973         col.prop(lamp, "show_cone")
974
975
976 class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
977     bl_label = "Preview"
978     bl_context = "world"
979     bl_options = {'DEFAULT_CLOSED'}
980
981     @classmethod
982     def poll(cls, context):
983         return context.world and CyclesButtonsPanel.poll(context)
984
985     def draw(self, context):
986         self.layout.template_preview(context.world)
987
988
989 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
990     bl_label = "Surface"
991     bl_context = "world"
992
993     @classmethod
994     def poll(cls, context):
995         return context.world and CyclesButtonsPanel.poll(context)
996
997     def draw(self, context):
998         layout = self.layout
999
1000         world = context.world
1001
1002         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
1003             layout.prop(world, "horizon_color", text="Color")
1004
1005
1006 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
1007     bl_label = "Volume"
1008     bl_context = "world"
1009     bl_options = {'DEFAULT_CLOSED'}
1010
1011     @classmethod
1012     def poll(cls, context):
1013         world = context.world
1014         return world and world.node_tree and CyclesButtonsPanel.poll(context)
1015
1016     def draw(self, context):
1017         layout = self.layout
1018
1019         world = context.world
1020         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
1021
1022
1023 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
1024     bl_label = "Ambient Occlusion"
1025     bl_context = "world"
1026
1027     @classmethod
1028     def poll(cls, context):
1029         return context.world and CyclesButtonsPanel.poll(context)
1030
1031     def draw_header(self, context):
1032         light = context.world.light_settings
1033         self.layout.prop(light, "use_ambient_occlusion", text="")
1034
1035     def draw(self, context):
1036         layout = self.layout
1037
1038         light = context.world.light_settings
1039         scene = context.scene
1040
1041         row = layout.row()
1042         sub = row.row()
1043         sub.active = light.use_ambient_occlusion or scene.render.use_simplify
1044         sub.prop(light, "ao_factor", text="Factor")
1045         row.prop(light, "distance", text="Distance")
1046
1047
1048 class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
1049     bl_label = "Mist Pass"
1050     bl_context = "world"
1051     bl_options = {'DEFAULT_CLOSED'}
1052
1053     @classmethod
1054     def poll(cls, context):
1055         if CyclesButtonsPanel.poll(context):
1056             if context.world:
1057                 for rl in context.scene.render.layers:
1058                     if rl.use_pass_mist:
1059                         return True
1060
1061         return False
1062
1063     def draw(self, context):
1064         layout = self.layout
1065
1066         world = context.world
1067
1068         split = layout.split(align=True)
1069         split.prop(world.mist_settings, "start")
1070         split.prop(world.mist_settings, "depth")
1071
1072         layout.prop(world.mist_settings, "falloff")
1073
1074
1075 class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
1076     bl_label = "Ray Visibility"
1077     bl_context = "world"
1078     bl_options = {'DEFAULT_CLOSED'}
1079
1080     @classmethod
1081     def poll(cls, context):
1082         return CyclesButtonsPanel.poll(context) and context.world
1083
1084     def draw(self, context):
1085         layout = self.layout
1086
1087         world = context.world
1088         visibility = world.cycles_visibility
1089
1090         flow = layout.column_flow()
1091
1092         flow.prop(visibility, "camera")
1093         flow.prop(visibility, "diffuse")
1094         flow.prop(visibility, "glossy")
1095         flow.prop(visibility, "transmission")
1096         flow.prop(visibility, "scatter")
1097
1098
1099 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
1100     bl_label = "Settings"
1101     bl_context = "world"
1102     bl_options = {'DEFAULT_CLOSED'}
1103
1104     @classmethod
1105     def poll(cls, context):
1106         return context.world and CyclesButtonsPanel.poll(context)
1107
1108     def draw(self, context):
1109         layout = self.layout
1110
1111         world = context.world
1112         cworld = world.cycles
1113         # cscene = context.scene.cycles
1114
1115         split = layout.split()
1116
1117         col = split.column()
1118
1119         col.label(text="Surface:")
1120         col.prop(cworld, "sample_as_light", text="Multiple Importance")
1121
1122         sub = col.column(align=True)
1123         sub.active = cworld.sample_as_light
1124         sub.prop(cworld, "sample_map_resolution")
1125         if use_branched_path(context):
1126             subsub = sub.row(align=True)
1127             subsub.active = use_sample_all_lights(context)
1128             subsub.prop(cworld, "samples")
1129         sub.prop(cworld, "max_bounces")
1130
1131         col = split.column()
1132         col.label(text="Volume:")
1133         sub = col.column()
1134         sub.active = use_cpu(context)
1135         sub.prop(cworld, "volume_sampling", text="")
1136         sub.prop(cworld, "volume_interpolation", text="")
1137         col.prop(cworld, "homogeneous_volume", text="Homogeneous")
1138
1139
1140 class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
1141     bl_label = "Preview"
1142     bl_context = "material"
1143     bl_options = {'DEFAULT_CLOSED'}
1144
1145     @classmethod
1146     def poll(cls, context):
1147         return context.material and CyclesButtonsPanel.poll(context)
1148
1149     def draw(self, context):
1150         self.layout.template_preview(context.material)
1151
1152
1153 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
1154     bl_label = "Surface"
1155     bl_context = "material"
1156
1157     @classmethod
1158     def poll(cls, context):
1159         return context.material and CyclesButtonsPanel.poll(context)
1160
1161     def draw(self, context):
1162         layout = self.layout
1163
1164         mat = context.material
1165         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
1166             layout.prop(mat, "diffuse_color")
1167
1168
1169 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
1170     bl_label = "Volume"
1171     bl_context = "material"
1172     bl_options = {'DEFAULT_CLOSED'}
1173
1174     @classmethod
1175     def poll(cls, context):
1176         mat = context.material
1177         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1178
1179     def draw(self, context):
1180         layout = self.layout
1181
1182         mat = context.material
1183         # cmat = mat.cycles
1184
1185         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
1186
1187
1188 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
1189     bl_label = "Displacement"
1190     bl_context = "material"
1191
1192     @classmethod
1193     def poll(cls, context):
1194         mat = context.material
1195         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1196
1197     def draw(self, context):
1198         layout = self.layout
1199
1200         mat = context.material
1201         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
1202
1203
1204 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
1205     bl_label = "Settings"
1206     bl_context = "material"
1207     bl_options = {'DEFAULT_CLOSED'}
1208
1209     @classmethod
1210     def poll(cls, context):
1211         return context.material and CyclesButtonsPanel.poll(context)
1212
1213     def draw(self, context):
1214         layout = self.layout
1215
1216         mat = context.material
1217         cmat = mat.cycles
1218
1219         split = layout.split()
1220         col = split.column()
1221         col.label(text="Surface:")
1222         col.prop(cmat, "sample_as_light", text="Multiple Importance")
1223         col.prop(cmat, "use_transparent_shadow")
1224
1225         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
1226             col.separator()
1227             col.label(text="Displacement:")
1228             col.prop(cmat, "displacement_method", text="")
1229
1230         col = split.column()
1231         col.label(text="Volume:")
1232         sub = col.column()
1233         sub.active = use_cpu(context)
1234         sub.prop(cmat, "volume_sampling", text="")
1235         sub.prop(cmat, "volume_interpolation", text="")
1236         col.prop(cmat, "homogeneous_volume", text="Homogeneous")
1237
1238         layout.separator()
1239         split = layout.split()
1240
1241         col = split.column(align=True)
1242         col.label("Viewport Color:")
1243         col.prop(mat, "diffuse_color", text="")
1244         col.prop(mat, "alpha")
1245
1246         col.separator()
1247         col.label("Viewport Alpha:")
1248         col.prop(mat.game_settings, "alpha_blend", text="")
1249
1250         col = split.column(align=True)
1251         col.label("Viewport Specular:")
1252         col.prop(mat, "specular_color", text="")
1253         col.prop(mat, "specular_hardness", text="Hardness")
1254
1255         col.separator()
1256         col.prop(mat, "pass_index")
1257
1258
1259 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
1260     bl_label = ""
1261     bl_context = "texture"
1262     bl_options = {'HIDE_HEADER'}
1263     COMPAT_ENGINES = {'CYCLES'}
1264
1265     def draw(self, context):
1266         layout = self.layout
1267
1268         tex = context.texture
1269         space = context.space_data
1270         pin_id = space.pin_id
1271         use_pin_id = space.use_pin_id
1272         user = context.texture_user
1273
1274         space.use_limited_texture_context = False
1275
1276         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
1277             pin_id = None
1278
1279         if not pin_id:
1280             layout.template_texture_user()
1281
1282         if user or pin_id:
1283             layout.separator()
1284
1285             split = layout.split(percentage=0.65)
1286             col = split.column()
1287
1288             if pin_id:
1289                 col.template_ID(space, "pin_id")
1290             else:
1291                 propname = context.texture_user_property.identifier
1292                 col.template_ID(user, propname, new="texture.new")
1293
1294             if tex:
1295                 split = layout.split(percentage=0.2)
1296                 split.label(text="Type:")
1297                 split.prop(tex, "type", text="")
1298
1299
1300 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
1301     bl_label = "Node"
1302     bl_context = "texture"
1303
1304     @classmethod
1305     def poll(cls, context):
1306         node = context.texture_node
1307         return node and CyclesButtonsPanel.poll(context)
1308
1309     def draw(self, context):
1310         layout = self.layout
1311
1312         node = context.texture_node
1313         ntree = node.id_data
1314         layout.template_node_view(ntree, node, None)
1315
1316
1317 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1318     bl_label = "Mapping"
1319     bl_context = "texture"
1320
1321     @classmethod
1322     def poll(cls, context):
1323         node = context.texture_node
1324         # TODO(sergey): perform a faster/nicer check?
1325         return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
1326
1327     def draw(self, context):
1328         layout = self.layout
1329
1330         node = context.texture_node
1331
1332         mapping = node.texture_mapping
1333
1334         layout.prop(mapping, "vector_type", expand=True)
1335
1336         row = layout.row()
1337
1338         row.column().prop(mapping, "translation")
1339         row.column().prop(mapping, "rotation")
1340         row.column().prop(mapping, "scale")
1341
1342         layout.label(text="Projection:")
1343
1344         row = layout.row()
1345         row.prop(mapping, "mapping_x", text="")
1346         row.prop(mapping, "mapping_y", text="")
1347         row.prop(mapping, "mapping_z", text="")
1348
1349
1350 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1351     bl_label = "Color"
1352     bl_context = "texture"
1353     bl_options = {'DEFAULT_CLOSED'}
1354
1355     @classmethod
1356     def poll(cls, context):
1357         # node = context.texture_node
1358         return False
1359         # return node and CyclesButtonsPanel.poll(context)
1360
1361     def draw(self, context):
1362         layout = self.layout
1363
1364         node = context.texture_node
1365
1366         mapping = node.color_mapping
1367
1368         split = layout.split()
1369
1370         col = split.column()
1371         col.label(text="Blend:")
1372         col.prop(mapping, "blend_type", text="")
1373         col.prop(mapping, "blend_factor", text="Factor")
1374         col.prop(mapping, "blend_color", text="")
1375
1376         col = split.column()
1377         col.label(text="Adjust:")
1378         col.prop(mapping, "brightness")
1379         col.prop(mapping, "contrast")
1380         col.prop(mapping, "saturation")
1381
1382         layout.separator()
1383
1384         layout.prop(mapping, "use_color_ramp", text="Ramp")
1385         if mapping.use_color_ramp:
1386             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1387
1388
1389 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
1390     bl_label = "Textures"
1391     bl_context = "particle"
1392     bl_options = {'DEFAULT_CLOSED'}
1393
1394     @classmethod
1395     def poll(cls, context):
1396         psys = context.particle_system
1397         return psys and CyclesButtonsPanel.poll(context)
1398
1399     def draw(self, context):
1400         layout = self.layout
1401
1402         psys = context.particle_system
1403         part = psys.settings
1404
1405         row = layout.row()
1406         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1407
1408         col = row.column(align=True)
1409         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1410         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1411         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1412
1413         if not part.active_texture:
1414             layout.template_ID(part, "active_texture", new="texture.new")
1415         else:
1416             slot = part.texture_slots[part.active_texture_index]
1417             layout.template_ID(slot, "texture", new="texture.new")
1418
1419
1420 class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
1421     bl_label = "Bake"
1422     bl_context = "render"
1423     bl_options = {'DEFAULT_CLOSED'}
1424     COMPAT_ENGINES = {'CYCLES'}
1425
1426     def draw(self, context):
1427         layout = self.layout
1428
1429         scene = context.scene
1430         cscene = scene.cycles
1431         cbk = scene.render.bake
1432
1433         layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
1434
1435         col = layout.column()
1436         col.prop(cscene, "bake_type")
1437
1438         col = layout.column()
1439
1440         if cscene.bake_type == 'NORMAL':
1441             col.prop(cbk, "normal_space", text="Space")
1442
1443             row = col.row(align=True)
1444             row.label(text="Swizzle:")
1445             row.prop(cbk, "normal_r", text="")
1446             row.prop(cbk, "normal_g", text="")
1447             row.prop(cbk, "normal_b", text="")
1448
1449         elif cscene.bake_type == 'COMBINED':
1450             row = col.row(align=True)
1451             row.prop(cbk, "use_pass_direct", toggle=True)
1452             row.prop(cbk, "use_pass_indirect", toggle=True)
1453
1454             split = col.split()
1455             split.active = cbk.use_pass_direct or cbk.use_pass_indirect
1456
1457             col = split.column()
1458             col.prop(cbk, "use_pass_diffuse")
1459             col.prop(cbk, "use_pass_glossy")
1460             col.prop(cbk, "use_pass_transmission")
1461
1462             col = split.column()
1463             col.prop(cbk, "use_pass_subsurface")
1464             col.prop(cbk, "use_pass_ambient_occlusion")
1465             col.prop(cbk, "use_pass_emit")
1466
1467         elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
1468             row = col.row(align=True)
1469             row.prop(cbk, "use_pass_direct", toggle=True)
1470             row.prop(cbk, "use_pass_indirect", toggle=True)
1471             row.prop(cbk, "use_pass_color", toggle=True)
1472
1473         layout.separator()
1474
1475         split = layout.split()
1476
1477         col = split.column()
1478         col.prop(cbk, "margin")
1479         col.prop(cbk, "use_clear")
1480
1481         col = split.column()
1482         col.prop(cbk, "use_selected_to_active")
1483         sub = col.column()
1484         sub.active = cbk.use_selected_to_active
1485         sub.prop(cbk, "use_cage", text="Cage")
1486         if cbk.use_cage:
1487             sub.prop(cbk, "cage_extrusion", text="Extrusion")
1488             sub.prop_search(cbk, "cage_object", scene, "objects", text="")
1489         else:
1490             sub.prop(cbk, "cage_extrusion", text="Ray Distance")
1491
1492
1493 class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
1494     bl_label = "Debug"
1495     bl_context = "render"
1496     bl_options = {'DEFAULT_CLOSED'}
1497     COMPAT_ENGINES = {'CYCLES'}
1498
1499     @classmethod
1500     def poll(cls, context):
1501         return CyclesButtonsPanel.poll(context) and bpy.app.debug_value == 256
1502
1503     def draw(self, context):
1504         layout = self.layout
1505
1506         scene = context.scene
1507         cscene = scene.cycles
1508
1509         col = layout.column()
1510
1511         col.label('CPU Flags:')
1512         row = col.row(align=True)
1513         row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
1514         row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
1515         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
1516         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
1517         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
1518         col.prop(cscene, "debug_use_qbvh")
1519         col.prop(cscene, "debug_use_cpu_split_kernel")
1520
1521         col = layout.column()
1522         col.label('CUDA Flags:')
1523         col.prop(cscene, "debug_use_cuda_adaptive_compile")
1524         col.prop(cscene, "debug_use_cuda_split_kernel")
1525
1526         col = layout.column()
1527         col.label('OpenCL Flags:')
1528         col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
1529         col.prop(cscene, "debug_opencl_device_type", text="Device")
1530         col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
1531         col.prop(cscene, "debug_use_opencl_debug", text="Debug")
1532
1533
1534 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1535     bl_label = "Cycles Hair Settings"
1536     bl_context = "particle"
1537
1538     @classmethod
1539     def poll(cls, context):
1540         scene = context.scene
1541         ccscene = scene.cycles_curves
1542         psys = context.particle_system
1543         use_curves = ccscene.use_curves and psys
1544         return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
1545
1546     def draw(self, context):
1547         layout = self.layout
1548
1549         psys = context.particle_settings
1550         cpsys = psys.cycles
1551
1552         row = layout.row()
1553         row.prop(cpsys, "shape", text="Shape")
1554
1555         layout.label(text="Thickness:")
1556         row = layout.row()
1557         row.prop(cpsys, "root_width", text="Root")
1558         row.prop(cpsys, "tip_width", text="Tip")
1559
1560         row = layout.row()
1561         row.prop(cpsys, "radius_scale", text="Scaling")
1562         row.prop(cpsys, "use_closetip", text="Close tip")
1563
1564
1565 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1566     bl_label = "Simplify"
1567     bl_context = "scene"
1568     COMPAT_ENGINES = {'CYCLES'}
1569
1570     def draw_header(self, context):
1571         rd = context.scene.render
1572         self.layout.prop(rd, "use_simplify", text="")
1573
1574     def draw(self, context):
1575         layout = self.layout
1576
1577         scene = context.scene
1578         rd = scene.render
1579         cscene = scene.cycles
1580
1581         layout.active = rd.use_simplify
1582
1583         col = layout.column(align=True)
1584         col.label(text="Subdivision")
1585         row = col.row(align=True)
1586         row.prop(rd, "simplify_subdivision", text="Viewport")
1587         row.prop(rd, "simplify_subdivision_render", text="Render")
1588
1589
1590         col = layout.column(align=True)
1591         col.label(text="Child Particles")
1592         row = col.row(align=True)
1593         row.prop(rd, "simplify_child_particles", text="Viewport")
1594         row.prop(rd, "simplify_child_particles_render", text="Render")
1595
1596         col = layout.column(align=True)
1597         split = col.split()
1598         sub = split.column()
1599         sub.label(text="Texture Limit Viewport")
1600         sub.prop(cscene, "texture_limit", text="")
1601         sub = split.column()
1602         sub.label(text="Texture Limit Render")
1603         sub.prop(cscene, "texture_limit_render", text="")
1604
1605         split = layout.split()
1606         col = split.column()
1607         col.prop(cscene, "use_camera_cull")
1608         row = col.row()
1609         row.active = cscene.use_camera_cull
1610         row.prop(cscene, "camera_cull_margin")
1611
1612         col = split.column()
1613         col.prop(cscene, "use_distance_cull")
1614         row = col.row()
1615         row.active = cscene.use_distance_cull
1616         row.prop(cscene, "distance_cull_margin", text="Distance")
1617
1618         split = layout.split()
1619         col = split.column()
1620         col.prop(cscene, "ao_bounces")
1621
1622         col = split.column()
1623         col.prop(cscene, "ao_bounces_render")
1624
1625 def draw_device(self, context):
1626     scene = context.scene
1627     layout = self.layout
1628
1629     if scene.render.engine == 'CYCLES':
1630         from . import engine
1631         cscene = scene.cycles
1632
1633         layout.prop(cscene, "feature_set")
1634
1635         split = layout.split(percentage=1/3)
1636         split.label("Device:")
1637         row = split.row()
1638         row.active = show_device_active(context)
1639         row.prop(cscene, "device", text="")
1640
1641         if engine.with_osl() and use_cpu(context):
1642             layout.prop(cscene, "shading_system")
1643
1644
1645 def draw_pause(self, context):
1646     layout = self.layout
1647     scene = context.scene
1648
1649     if scene.render.engine == "CYCLES":
1650         view = context.space_data
1651
1652         if view.viewport_shade == 'RENDERED':
1653             cscene = scene.cycles
1654             layername = scene.render.layers.active.name
1655             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1656             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1657
1658
1659 def get_panels():
1660     exclude_panels = {
1661         'DATA_PT_area',
1662         'DATA_PT_camera_dof',
1663         'DATA_PT_falloff_curve',
1664         'DATA_PT_lamp',
1665         'DATA_PT_preview',
1666         'DATA_PT_shadow',
1667         'DATA_PT_spot',
1668         'DATA_PT_sunsky',
1669         'MATERIAL_PT_context_material',
1670         'MATERIAL_PT_diffuse',
1671         'MATERIAL_PT_flare',
1672         'MATERIAL_PT_halo',
1673         'MATERIAL_PT_mirror',
1674         'MATERIAL_PT_options',
1675         'MATERIAL_PT_pipeline',
1676         'MATERIAL_PT_preview',
1677         'MATERIAL_PT_shading',
1678         'MATERIAL_PT_shadow',
1679         'MATERIAL_PT_specular',
1680         'MATERIAL_PT_sss',
1681         'MATERIAL_PT_strand',
1682         'MATERIAL_PT_transp',
1683         'MATERIAL_PT_volume_density',
1684         'MATERIAL_PT_volume_integration',
1685         'MATERIAL_PT_volume_lighting',
1686         'MATERIAL_PT_volume_options',
1687         'MATERIAL_PT_volume_shading',
1688         'MATERIAL_PT_volume_transp',
1689         'RENDERLAYER_PT_layer_options',
1690         'RENDERLAYER_PT_layer_passes',
1691         'RENDERLAYER_PT_views',
1692         'RENDER_PT_antialiasing',
1693         'RENDER_PT_bake',
1694         'RENDER_PT_motion_blur',
1695         'RENDER_PT_performance',
1696         'RENDER_PT_post_processing',
1697         'RENDER_PT_shading',
1698         'SCENE_PT_simplify',
1699         'TEXTURE_PT_context_texture',
1700         'WORLD_PT_ambient_occlusion',
1701         'WORLD_PT_environment_lighting',
1702         'WORLD_PT_gather',
1703         'WORLD_PT_indirect_lighting',
1704         'WORLD_PT_mist',
1705         'WORLD_PT_preview',
1706         'WORLD_PT_world'
1707         }
1708
1709     panels = []
1710     for panel in bpy.types.Panel.__subclasses__():
1711         if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
1712             if panel.__name__ not in exclude_panels:
1713                 panels.append(panel)
1714
1715     return panels
1716
1717
1718 classes = (
1719     CYCLES_MT_sampling_presets,
1720     CYCLES_MT_integrator_presets,
1721     CyclesRender_PT_sampling,
1722     CyclesRender_PT_geometry,
1723     CyclesRender_PT_light_paths,
1724     CyclesRender_PT_motion_blur,
1725     CyclesRender_PT_film,
1726     CyclesRender_PT_performance,
1727     CyclesRender_PT_layer_options,
1728     CyclesRender_PT_layer_passes,
1729     CyclesRender_PT_views,
1730     Cycles_PT_post_processing,
1731     CyclesCamera_PT_dof,
1732     Cycles_PT_context_material,
1733     CyclesObject_PT_motion_blur,
1734     CyclesObject_PT_cycles_settings,
1735     CYCLES_OT_use_shading_nodes,
1736     CyclesLamp_PT_preview,
1737     CyclesLamp_PT_lamp,
1738     CyclesLamp_PT_nodes,
1739     CyclesLamp_PT_spot,
1740     CyclesWorld_PT_preview,
1741     CyclesWorld_PT_surface,
1742     CyclesWorld_PT_volume,
1743     CyclesWorld_PT_ambient_occlusion,
1744     CyclesWorld_PT_mist,
1745     CyclesWorld_PT_ray_visibility,
1746     CyclesWorld_PT_settings,
1747     CyclesMaterial_PT_preview,
1748     CyclesMaterial_PT_surface,
1749     CyclesMaterial_PT_volume,
1750     CyclesMaterial_PT_displacement,
1751     CyclesMaterial_PT_settings,
1752     CyclesTexture_PT_context,
1753     CyclesTexture_PT_node,
1754     CyclesTexture_PT_mapping,
1755     CyclesTexture_PT_colors,
1756     CyclesParticle_PT_textures,
1757     CyclesRender_PT_bake,
1758     CyclesRender_PT_debug,
1759     CyclesParticle_PT_CurveSettings,
1760     CyclesScene_PT_simplify,
1761 )
1762
1763
1764 def register():
1765     from bpy.utils import register_class
1766
1767     bpy.types.RENDER_PT_render.append(draw_device)
1768     bpy.types.VIEW3D_HT_header.append(draw_pause)
1769
1770     for panel in get_panels():
1771         panel.COMPAT_ENGINES.add('CYCLES')
1772
1773     for cls in classes:
1774         register_class(cls)
1775
1776
1777 def unregister():
1778     from bpy.utils import unregister_class
1779
1780     bpy.types.RENDER_PT_render.remove(draw_device)
1781     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1782
1783     for panel in get_panels():
1784         if 'CYCLES' in panel.COMPAT_ENGINES:
1785             panel.COMPAT_ENGINES.remove('CYCLES')
1786
1787     for cls in classes:
1788         unregister_class(cls)