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