Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / blender / addon / properties.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.props import (
21     BoolProperty,
22     EnumProperty,
23     FloatProperty,
24     IntProperty,
25     PointerProperty,
26     StringProperty,
27 )
28
29 # enums
30
31 import _cycles
32
33 enum_devices = (
34     ('CPU', "CPU", "Use CPU for rendering"),
35     ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in the system tab in the user preferences"),
36 )
37
38 if _cycles.with_network:
39     enum_devices += (('NETWORK', "Networked Device", "Use networked device for rendering"),)
40
41 enum_feature_set = (
42     ('SUPPORTED', "Supported", "Only use finished and supported features"),
43     ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future", 'ERROR', 1),
44 )
45
46 enum_displacement_methods = (
47     ('BUMP', "Bump Only", "Bump mapping to simulate the appearance of displacement"),
48     ('DISPLACEMENT', "Displacement Only", "Use true displacement of surface only, requires fine subdivision"),
49     ('BOTH', "Displacement and Bump", "Combination of true displacement and bump mapping for finer detail"),
50 )
51
52 enum_bvh_layouts = (
53     ('BVH2', "BVH2", "", 1),
54     ('BVH4', "BVH4", "", 2),
55 )
56
57 enum_bvh_types = (
58     ('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
59     ('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
60 )
61
62 enum_filter_types = (
63     ('BOX', "Box", "Box filter"),
64     ('GAUSSIAN', "Gaussian", "Gaussian filter"),
65     ('BLACKMAN_HARRIS', "Blackman-Harris", "Blackman-Harris filter"),
66 )
67
68 enum_aperture_types = (
69     ('RADIUS', "Radius", "Directly change the size of the aperture"),
70     ('FSTOP', "F-stop", "Change the size of the aperture by f-stop"),
71 )
72
73 enum_panorama_types = (
74     ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
75     ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
76     ('FISHEYE_EQUISOLID', "Fisheye Equisolid",
77                           "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
78     ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
79 )
80
81 enum_curve_primitives = (
82     ('TRIANGLES', "Triangles", "Create triangle geometry around strands"),
83     ('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"),
84     ('CURVE_SEGMENTS', "Curve Segments", "Use segmented cardinal curve primitives"),
85 )
86
87 enum_triangle_curves = (
88     ('CAMERA_TRIANGLES', "Planes", "Create individual triangles forming planes that face camera"),
89     ('TESSELLATED_TRIANGLES', "Tessellated", "Create mesh surrounding each strand"),
90 )
91
92 enum_curve_shape = (
93     ('RIBBONS', "Ribbons", "Ignore thickness of each strand"),
94     ('THICK', "Thick", "Use thickness of strand when rendering"),
95 )
96
97 enum_tile_order = (
98     ('CENTER', "Center", "Render from center to the edges"),
99     ('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"),
100     ('LEFT_TO_RIGHT', "Left to Right", "Render from left to right"),
101     ('TOP_TO_BOTTOM', "Top to Bottom", "Render from top to bottom"),
102     ('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"),
103     ('HILBERT_SPIRAL', "Hilbert Spiral", "Render in a Hilbert Spiral"),
104 )
105
106 enum_use_layer_samples = (
107     ('USE', "Use", "Per render layer number of samples override scene samples"),
108     ('BOUNDED', "Bounded", "Bound per render layer number of samples by global samples"),
109     ('IGNORE', "Ignore", "Ignore per render layer number of samples"),
110 )
111
112 enum_sampling_pattern = (
113     ('SOBOL', "Sobol", "Use Sobol random sampling pattern"),
114     ('CORRELATED_MUTI_JITTER', "Correlated Multi-Jitter", "Use Correlated Multi-Jitter random sampling pattern"),
115 )
116
117 enum_integrator = (
118     ('BRANCHED_PATH', "Branched Path Tracing", "Path tracing integrator that branches on the first bounce, giving more control over the number of light and material samples"),
119     ('PATH', "Path Tracing", "Pure path tracing integrator"),
120 )
121
122 enum_volume_sampling = (
123     ('DISTANCE', "Distance", "Use distance sampling, best for dense volumes with lights far away"),
124     ('EQUIANGULAR', "Equiangular", "Use equiangular sampling, best for volumes with low density with light inside or near the volume"),
125     ('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
126 )
127
128 enum_volume_interpolation = (
129     ('LINEAR', "Linear", "Good smoothness and speed"),
130     ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower")
131 )
132
133 enum_world_mis = (
134     ('NONE', "None", "Don't sample the background, faster but might cause noise for non-solid backgrounds"),
135     ('AUTOMATIC', "Auto", "Automatically try to determine the best setting"),
136     ('MANUAL', "Manual", "Manually set the resolution of the sampling map, higher values are slower and require more memory but reduce noise")
137 )
138
139 enum_device_type = (
140     ('CPU', "CPU", "CPU", 0),
141     ('CUDA', "CUDA", "CUDA", 1),
142     ('OPENCL', "OpenCL", "OpenCL", 2)
143 )
144
145 enum_texture_limit = (
146     ('OFF', "No Limit", "No texture size limit", 0),
147     ('128', "128", "Limit texture size to 128 pixels", 1),
148     ('256', "256", "Limit texture size to 256 pixels", 2),
149     ('512', "512", "Limit texture size to 512 pixels", 3),
150     ('1024', "1024", "Limit texture size to 1024 pixels", 4),
151     ('2048', "2048", "Limit texture size to 2048 pixels", 5),
152     ('4096', "4096", "Limit texture size to 4096 pixels", 6),
153     ('8192', "8192", "Limit texture size to 8192 pixels", 7),
154 )
155
156
157 class CyclesRenderSettings(bpy.types.PropertyGroup):
158     @classmethod
159     def register(cls):
160         bpy.types.Scene.cycles = PointerProperty(
161             name="Cycles Render Settings",
162             description="Cycles render settings",
163             type=cls,
164         )
165         cls.device = EnumProperty(
166             name="Device",
167             description="Device to use for rendering",
168             items=enum_devices,
169             default='CPU',
170         )
171         cls.feature_set = EnumProperty(
172             name="Feature Set",
173             description="Feature set to use for rendering",
174             items=enum_feature_set,
175             default='SUPPORTED',
176         )
177         cls.shading_system = BoolProperty(
178             name="Open Shading Language",
179             description="Use Open Shading Language (CPU rendering only)",
180         )
181
182         cls.progressive = EnumProperty(
183             name="Integrator",
184             description="Method to sample lights and materials",
185             items=enum_integrator,
186             default='PATH',
187         )
188
189         cls.use_square_samples = BoolProperty(
190             name="Square Samples",
191             description="Square sampling values for easier artist control",
192             default=False,
193         )
194
195         cls.samples = IntProperty(
196             name="Samples",
197             description="Number of samples to render for each pixel",
198             min=1, max=2147483647,
199             default=128,
200         )
201         cls.preview_samples = IntProperty(
202             name="Preview Samples",
203             description="Number of samples to render in the viewport, unlimited if 0",
204             min=0, max=2147483647,
205             default=32,
206         )
207         cls.preview_pause = BoolProperty(
208             name="Pause Preview",
209             description="Pause all viewport preview renders",
210             default=False,
211         )
212         cls.aa_samples = IntProperty(
213             name="AA Samples",
214             description="Number of antialiasing samples to render for each pixel",
215             min=1, max=2097151,
216             default=128,
217         )
218         cls.preview_aa_samples = IntProperty(
219             name="AA Samples",
220             description="Number of antialiasing samples to render in the viewport, unlimited if 0",
221             min=0, max=2097151,
222             default=32,
223         )
224         cls.diffuse_samples = IntProperty(
225             name="Diffuse Samples",
226             description="Number of diffuse bounce samples to render for each AA sample",
227             min=1, max=1024,
228             default=1,
229         )
230         cls.glossy_samples = IntProperty(
231             name="Glossy Samples",
232             description="Number of glossy bounce samples to render for each AA sample",
233             min=1, max=1024,
234             default=1,
235         )
236         cls.transmission_samples = IntProperty(
237             name="Transmission Samples",
238             description="Number of transmission bounce samples to render for each AA sample",
239             min=1, max=1024,
240             default=1,
241         )
242         cls.ao_samples = IntProperty(
243             name="Ambient Occlusion Samples",
244             description="Number of ambient occlusion samples to render for each AA sample",
245             min=1, max=1024,
246             default=1,
247         )
248         cls.mesh_light_samples = IntProperty(
249             name="Mesh Light Samples",
250             description="Number of mesh emission light samples to render for each AA sample",
251             min=1, max=1024,
252             default=1,
253         )
254
255         cls.subsurface_samples = IntProperty(
256             name="Subsurface Samples",
257             description="Number of subsurface scattering samples to render for each AA sample",
258             min=1, max=1024,
259             default=1,
260         )
261
262         cls.volume_samples = IntProperty(
263             name="Volume Samples",
264             description="Number of volume scattering samples to render for each AA sample",
265             min=1, max=1024,
266             default=1,
267         )
268
269         cls.sampling_pattern = EnumProperty(
270             name="Sampling Pattern",
271             description="Random sampling pattern used by the integrator",
272             items=enum_sampling_pattern,
273             default='SOBOL',
274         )
275
276         cls.use_layer_samples = EnumProperty(
277             name="Layer Samples",
278             description="How to use per render layer sample settings",
279             items=enum_use_layer_samples,
280             default='USE',
281         )
282
283         cls.sample_all_lights_direct = BoolProperty(
284             name="Sample All Direct Lights",
285             description="Sample all lights (for direct samples), rather than randomly picking one",
286             default=True,
287         )
288
289         cls.sample_all_lights_indirect = BoolProperty(
290             name="Sample All Indirect Lights",
291             description="Sample all lights (for indirect samples), rather than randomly picking one",
292             default=True,
293         )
294         cls.light_sampling_threshold = FloatProperty(
295             name="Light Sampling Threshold",
296             description="Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). "
297             "Zero disables the test and never ignores lights",
298             min=0.0, max=1.0,
299             default=0.01,
300         )
301
302         cls.caustics_reflective = BoolProperty(
303             name="Reflective Caustics",
304             description="Use reflective caustics, resulting in a brighter image (more noise but added realism)",
305             default=True,
306         )
307
308         cls.caustics_refractive = BoolProperty(
309             name="Refractive Caustics",
310             description="Use refractive caustics, resulting in a brighter image (more noise but added realism)",
311             default=True,
312         )
313
314         cls.blur_glossy = FloatProperty(
315             name="Filter Glossy",
316             description="Adaptively blur glossy shaders after blurry bounces, "
317             "to reduce noise at the cost of accuracy",
318             min=0.0, max=10.0,
319             default=1.0,
320         )
321
322         cls.max_bounces = IntProperty(
323             name="Max Bounces",
324             description="Total maximum number of bounces",
325             min=0, max=1024,
326             default=12,
327         )
328
329         cls.diffuse_bounces = IntProperty(
330             name="Diffuse Bounces",
331             description="Maximum number of diffuse reflection bounces, bounded by total maximum",
332             min=0, max=1024,
333             default=4,
334         )
335         cls.glossy_bounces = IntProperty(
336             name="Glossy Bounces",
337             description="Maximum number of glossy reflection bounces, bounded by total maximum",
338             min=0, max=1024,
339             default=4,
340         )
341         cls.transmission_bounces = IntProperty(
342             name="Transmission Bounces",
343             description="Maximum number of transmission bounces, bounded by total maximum",
344             min=0, max=1024,
345             default=12,
346         )
347         cls.volume_bounces = IntProperty(
348             name="Volume Bounces",
349             description="Maximum number of volumetric scattering events",
350             min=0, max=1024,
351             default=0,
352         )
353
354         cls.transparent_max_bounces = IntProperty(
355             name="Transparent Max Bounces",
356             description="Maximum number of transparent bounces",
357             min=0, max=1024,
358             default=8,
359         )
360
361         cls.volume_step_size = FloatProperty(
362             name="Step Size",
363             description="Distance between volume shader samples when rendering the volume "
364             "(lower values give more accurate and detailed results, but also increased render time)",
365             default=0.1,
366             min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0, precision=4
367         )
368
369         cls.volume_max_steps = IntProperty(
370             name="Max Steps",
371             description="Maximum number of steps through the volume before giving up, "
372             "to avoid extremely long render times with big objects or small step sizes",
373             default=1024,
374             min=2, max=65536
375         )
376
377         cls.dicing_rate = FloatProperty(
378             name="Dicing Rate",
379             description="Size of a micropolygon in pixels",
380             min=0.1, max=1000.0, soft_min=0.5,
381             default=1.0,
382             subtype="PIXEL"
383         )
384         cls.preview_dicing_rate = FloatProperty(
385             name="Preview Dicing Rate",
386             description="Size of a micropolygon in pixels during preview render",
387             min=0.1, max=1000.0, soft_min=0.5,
388             default=8.0,
389             subtype="PIXEL"
390         )
391
392         cls.max_subdivisions = IntProperty(
393             name="Max Subdivisions",
394             description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation",
395             min=0, max=16,
396             default=12,
397         )
398
399         cls.dicing_camera = PointerProperty(
400             name="Dicing Camera",
401             description="Camera to use as reference point when subdividing geometry, useful to avoid crawling "
402             "artifacts in animations when the scene camera is moving",
403             type=bpy.types.Object,
404             poll=lambda self, obj: obj.type == 'CAMERA',
405         )
406         cls.offscreen_dicing_scale = FloatProperty(
407             name="Offscreen Dicing Scale",
408             description="Multiplier for dicing rate of geometry outside of the camera view. The dicing rate "
409             "of objects is gradually increased the further they are outside the camera view. "
410             "Lower values provide higher quality reflections and shadows for off screen objects, "
411             "while higher values use less memory",
412             min=1.0, soft_max=25.0,
413             default=4.0,
414         )
415
416         cls.film_exposure = FloatProperty(
417             name="Exposure",
418             description="Image brightness scale",
419             min=0.0, max=10.0,
420             default=1.0,
421         )
422         cls.film_transparent = BoolProperty(
423             name="Transparent",
424             description="World background is transparent, for compositing the render over another background",
425             default=False,
426         )
427         cls.film_transparent_glass = BoolProperty(
428             name="Transparent Glass",
429             description="Render transmissive surfaces as transparent, for compositing glass over another background",
430             default=False,
431         )
432         cls.film_transparent_roughness = FloatProperty(
433             name="Transparent Roughness Threshold",
434             description="For transparent transmission, keep surfaces with roughness above the threshold opaque",
435             min=0.0, max=1.0,
436             default=0.1,
437         )
438
439         # Really annoyingly, we have to keep it around for a few releases,
440         # otherwise forward compatibility breaks in really bad manner: CRASH!
441         #
442         # TODO(sergey): Remove this during 2.8x series of Blender.
443         cls.filter_type = EnumProperty(
444             name="Filter Type",
445             description="Pixel filter type",
446             items=enum_filter_types,
447             default='BLACKMAN_HARRIS',
448         )
449
450         cls.pixel_filter_type = EnumProperty(
451             name="Filter Type",
452             description="Pixel filter type",
453             items=enum_filter_types,
454             default='BLACKMAN_HARRIS',
455         )
456
457         cls.filter_width = FloatProperty(
458             name="Filter Width",
459             description="Pixel filter width",
460             min=0.01, max=10.0,
461             default=1.5,
462         )
463
464         cls.seed = IntProperty(
465             name="Seed",
466             description="Seed value for integrator to get different noise patterns",
467             min=0, max=2147483647,
468             default=0,
469         )
470
471         cls.use_animated_seed = BoolProperty(
472             name="Use Animated Seed",
473             description="Use different seed values (and hence noise patterns) at different frames",
474             default=False,
475         )
476
477         cls.sample_clamp_direct = FloatProperty(
478             name="Clamp Direct",
479             description="If non-zero, the maximum value for a direct sample, "
480             "higher values will be scaled down to avoid too "
481             "much noise and slow convergence at the cost of accuracy",
482             min=0.0, max=1e8,
483             default=0.0,
484         )
485
486         cls.sample_clamp_indirect = FloatProperty(
487             name="Clamp Indirect",
488             description="If non-zero, the maximum value for an indirect sample, "
489             "higher values will be scaled down to avoid too "
490             "much noise and slow convergence at the cost of accuracy",
491             min=0.0, max=1e8,
492             default=10.0,
493         )
494
495         cls.debug_tile_size = IntProperty(
496             name="Tile Size",
497             description="",
498             min=1, max=4096,
499             default=1024,
500         )
501
502         cls.preview_start_resolution = IntProperty(
503             name="Start Resolution",
504             description="Resolution to start rendering preview at, "
505             "progressively increasing it to the full viewport size",
506             min=8, max=16384,
507             default=64,
508         )
509
510         cls.debug_reset_timeout = FloatProperty(
511             name="Reset timeout",
512             description="",
513             min=0.01, max=10.0,
514             default=0.1,
515         )
516         cls.debug_cancel_timeout = FloatProperty(
517             name="Cancel timeout",
518             description="",
519             min=0.01, max=10.0,
520             default=0.1,
521         )
522         cls.debug_text_timeout = FloatProperty(
523             name="Text timeout",
524             description="",
525             min=0.01, max=10.0,
526             default=1.0,
527         )
528
529         cls.debug_bvh_type = EnumProperty(
530             name="Viewport BVH Type",
531             description="Choose between faster updates, or faster render",
532             items=enum_bvh_types,
533             default='DYNAMIC_BVH',
534         )
535         cls.debug_use_spatial_splits = BoolProperty(
536             name="Use Spatial Splits",
537             description="Use BVH spatial splits: longer builder time, faster render",
538             default=False,
539         )
540         cls.debug_use_hair_bvh = BoolProperty(
541             name="Use Hair BVH",
542             description="Use special type BVH optimized for hair (uses more ram but renders faster)",
543             default=True,
544         )
545         cls.debug_bvh_time_steps = IntProperty(
546             name="BVH Time Steps",
547             description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
548             default=0,
549             min=0, max=16,
550         )
551         cls.tile_order = EnumProperty(
552             name="Tile Order",
553             description="Tile order for rendering",
554             items=enum_tile_order,
555             default='HILBERT_SPIRAL',
556             options=set(),  # Not animatable!
557         )
558         cls.use_progressive_refine = BoolProperty(
559             name="Progressive Refine",
560             description="Instead of rendering each tile until it is finished, "
561             "refine the whole image progressively "
562             "(this renders somewhat slower, "
563             "but time can be saved by manually stopping the render when the noise is low enough)",
564             default=False,
565         )
566
567         cls.bake_type = EnumProperty(
568             name="Bake Type",
569             default='COMBINED',
570             description="Type of pass to bake",
571             items=(
572                 ('COMBINED', "Combined", ""),
573                 ('AO', "Ambient Occlusion", ""),
574                 ('SHADOW', "Shadow", ""),
575                 ('NORMAL', "Normal", ""),
576                 ('UV', "UV", ""),
577                 ('ROUGHNESS', "Roughness", ""),
578                 ('EMIT', "Emit", ""),
579                 ('ENVIRONMENT', "Environment", ""),
580                 ('DIFFUSE', "Diffuse", ""),
581                 ('GLOSSY', "Glossy", ""),
582                 ('TRANSMISSION', "Transmission", ""),
583                 ('SUBSURFACE', "Subsurface", ""),
584             ),
585         )
586
587         cls.use_camera_cull = BoolProperty(
588             name="Use Camera Cull",
589             description="Allow objects to be culled based on the camera frustum",
590             default=False,
591         )
592
593         cls.camera_cull_margin = FloatProperty(
594             name="Camera Cull Margin",
595             description="Margin for the camera space culling",
596             default=0.1,
597             min=0.0, max=5.0
598         )
599
600         cls.use_distance_cull = BoolProperty(
601             name="Use Distance Cull",
602             description="Allow objects to be culled based on the distance from camera",
603             default=False,
604         )
605
606         cls.distance_cull_margin = FloatProperty(
607             name="Cull Distance",
608             description="Cull objects which are further away from camera than this distance",
609             default=50,
610             min=0.0
611         )
612
613         cls.motion_blur_position = EnumProperty(
614             name="Motion Blur Position",
615             default='CENTER',
616             description="Offset for the shutter's time interval, allows to change the motion blur trails",
617             items=(
618                 ('START', "Start on Frame", "The shutter opens at the current frame"),
619                 ('CENTER', "Center on Frame", "The shutter is open during the current frame"),
620                 ('END', "End on Frame", "The shutter closes at the current frame"),
621             ),
622         )
623
624         cls.rolling_shutter_type = EnumProperty(
625             name="Shutter Type",
626             default='NONE',
627             description="Type of rolling shutter effect matching CMOS-based cameras",
628             items=(
629                 ('NONE', "None", "No rolling shutter effect used"),
630                 ('TOP', "Top-Bottom", "Sensor is being scanned from top to bottom")
631                 # TODO(seergey): Are there real cameras with different scanning direction?
632             ),
633         )
634
635         cls.rolling_shutter_duration = FloatProperty(
636             name="Rolling Shutter Duration",
637             description="Scanline \"exposure\" time for the rolling shutter effect",
638             default=0.1,
639             min=0.0, max=1.0,
640         )
641
642         cls.texture_limit = EnumProperty(
643             name="Viewport Texture Limit",
644             default='OFF',
645             description="Limit texture size used by viewport rendering",
646             items=enum_texture_limit
647         )
648
649         cls.texture_limit_render = EnumProperty(
650             name="Render Texture Limit",
651             default='OFF',
652             description="Limit texture size used by final rendering",
653             items=enum_texture_limit
654         )
655
656         cls.ao_bounces = IntProperty(
657             name="AO Bounces",
658             default=0,
659             description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
660             min=0, max=1024,
661         )
662
663         cls.ao_bounces_render = IntProperty(
664             name="AO Bounces Render",
665             default=0,
666             description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
667             min=0, max=1024,
668         )
669
670         # Various fine-tuning debug flags
671
672         def devices_update_callback(self, context):
673             import _cycles
674             scene = context.scene.as_pointer()
675             return _cycles.debug_flags_update(scene)
676
677         cls.debug_use_cpu_avx2 = BoolProperty(name="AVX2", default=True)
678         cls.debug_use_cpu_avx = BoolProperty(name="AVX", default=True)
679         cls.debug_use_cpu_sse41 = BoolProperty(name="SSE41", default=True)
680         cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True)
681         cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True)
682         cls.debug_bvh_layout = EnumProperty(
683             name="BVH Layout",
684             items=enum_bvh_layouts,
685             default='BVH4',
686         )
687         cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False)
688
689         cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False)
690         cls.debug_use_cuda_split_kernel = BoolProperty(name="Split Kernel", default=False)
691
692         cls.debug_opencl_kernel_type = EnumProperty(
693             name="OpenCL Kernel Type",
694             default='DEFAULT',
695             items=(
696                 ('DEFAULT', "Default", ""),
697                 ('MEGA', "Mega", ""),
698                 ('SPLIT', "Split", ""),
699             ),
700             update=devices_update_callback
701         )
702
703         cls.debug_opencl_device_type = EnumProperty(
704             name="OpenCL Device Type",
705             default='ALL',
706             items=(
707                 ('NONE', "None", ""),
708                 ('ALL', "All", ""),
709                 ('DEFAULT', "Default", ""),
710                 ('CPU', "CPU", ""),
711                 ('GPU', "GPU", ""),
712                 ('ACCELERATOR', "Accelerator", ""),
713             ),
714             update=devices_update_callback
715         )
716
717         cls.debug_opencl_kernel_single_program = BoolProperty(
718             name="Single Program",
719             default=True,
720             update=devices_update_callback,
721         )
722
723         cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
724
725         cls.debug_opencl_mem_limit = IntProperty(name="Memory limit", default=0,
726                                                  description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)")
727
728     @classmethod
729     def unregister(cls):
730         del bpy.types.Scene.cycles
731
732
733 class CyclesCameraSettings(bpy.types.PropertyGroup):
734     @classmethod
735     def register(cls):
736         import math
737
738         bpy.types.Camera.cycles = PointerProperty(
739             name="Cycles Camera Settings",
740             description="Cycles camera settings",
741             type=cls,
742         )
743
744         cls.aperture_type = EnumProperty(
745             name="Aperture Type",
746             description="Use f-stop number or aperture radius",
747             items=enum_aperture_types,
748             default='RADIUS',
749         )
750         cls.aperture_fstop = FloatProperty(
751             name="Aperture f-stop",
752             description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
753             min=0.0, soft_min=0.1, soft_max=64.0,
754             default=5.6,
755             step=10,
756             precision=1,
757         )
758         cls.aperture_size = FloatProperty(
759             name="Aperture Size",
760             description="Radius of the aperture for depth of field (higher values give more defocus)",
761             min=0.0, soft_max=10.0,
762             default=0.0,
763             step=1,
764             precision=4,
765             subtype='DISTANCE',
766         )
767         cls.aperture_blades = IntProperty(
768             name="Aperture Blades",
769             description="Number of blades in aperture for polygonal bokeh (at least 3)",
770             min=0, max=100,
771             default=0,
772         )
773         cls.aperture_rotation = FloatProperty(
774             name="Aperture Rotation",
775             description="Rotation of blades in aperture",
776             soft_min=-math.pi, soft_max=math.pi,
777             subtype='ANGLE',
778             default=0,
779         )
780         cls.aperture_ratio = FloatProperty(
781             name="Aperture Ratio",
782             description="Distortion to simulate anamorphic lens bokeh",
783             min=0.01, soft_min=1.0, soft_max=2.0,
784             default=1.0,
785             precision=4,
786         )
787         cls.panorama_type = EnumProperty(
788             name="Panorama Type",
789             description="Distortion to use for the calculation",
790             items=enum_panorama_types,
791             default='FISHEYE_EQUISOLID',
792         )
793         cls.fisheye_fov = FloatProperty(
794             name="Field of View",
795             description="Field of view for the fisheye lens",
796             min=0.1745, soft_max=2.0 * math.pi, max=10.0 * math.pi,
797             subtype='ANGLE',
798             default=math.pi,
799         )
800         cls.fisheye_lens = FloatProperty(
801             name="Fisheye Lens",
802             description="Lens focal length (mm)",
803             min=0.01, soft_max=15.0, max=100.0,
804             default=10.5,
805         )
806         cls.latitude_min = FloatProperty(
807             name="Min Latitude",
808             description="Minimum latitude (vertical angle) for the equirectangular lens",
809             min=-0.5 * math.pi, max=0.5 * math.pi,
810             subtype='ANGLE',
811             default=-0.5 * math.pi,
812         )
813         cls.latitude_max = FloatProperty(
814             name="Max Latitude",
815             description="Maximum latitude (vertical angle) for the equirectangular lens",
816             min=-0.5 * math.pi, max=0.5 * math.pi,
817             subtype='ANGLE',
818             default=0.5 * math.pi,
819         )
820         cls.longitude_min = FloatProperty(
821             name="Min Longitude",
822             description="Minimum longitude (horizontal angle) for the equirectangular lens",
823             min=-math.pi, max=math.pi,
824             subtype='ANGLE',
825             default=-math.pi,
826         )
827         cls.longitude_max = FloatProperty(
828             name="Max Longitude",
829             description="Maximum longitude (horizontal angle) for the equirectangular lens",
830             min=-math.pi, max=math.pi,
831             subtype='ANGLE',
832             default=math.pi,
833         )
834
835     @classmethod
836     def unregister(cls):
837         del bpy.types.Camera.cycles
838
839
840 class CyclesMaterialSettings(bpy.types.PropertyGroup):
841     @classmethod
842     def register(cls):
843         bpy.types.Material.cycles = PointerProperty(
844             name="Cycles Material Settings",
845             description="Cycles material settings",
846             type=cls,
847         )
848         cls.sample_as_light = BoolProperty(
849             name="Multiple Importance Sample",
850             description="Use multiple importance sampling for this material, "
851             "disabling may reduce overall noise for large "
852             "objects that emit little light compared to other light sources",
853             default=True,
854         )
855         cls.use_transparent_shadow = BoolProperty(
856             name="Transparent Shadows",
857             description="Use transparent shadows for this material if it contains a Transparent BSDF, "
858             "disabling will render faster but not give accurate shadows",
859             default=True,
860         )
861         cls.homogeneous_volume = BoolProperty(
862             name="Homogeneous Volume",
863             description="When using volume rendering, assume volume has the same density everywhere "
864             "(not using any textures), for faster rendering",
865             default=False,
866         )
867         cls.volume_sampling = EnumProperty(
868             name="Volume Sampling",
869             description="Sampling method to use for volumes",
870             items=enum_volume_sampling,
871             default='MULTIPLE_IMPORTANCE',
872         )
873
874         cls.volume_interpolation = EnumProperty(
875             name="Volume Interpolation",
876             description="Interpolation method to use for smoke/fire volumes",
877             items=enum_volume_interpolation,
878             default='LINEAR',
879         )
880
881         cls.displacement_method = EnumProperty(
882             name="Displacement Method",
883             description="Method to use for the displacement",
884             items=enum_displacement_methods,
885             default='DISPLACEMENT',
886         )
887
888     @classmethod
889     def unregister(cls):
890         del bpy.types.Material.cycles
891
892
893 class CyclesLightSettings(bpy.types.PropertyGroup):
894     @classmethod
895     def register(cls):
896         bpy.types.Light.cycles = PointerProperty(
897             name="Cycles Light Settings",
898             description="Cycles light settings",
899             type=cls,
900         )
901         cls.cast_shadow = BoolProperty(
902             name="Cast Shadow",
903             description="Light casts shadows",
904             default=True,
905         )
906         cls.samples = IntProperty(
907             name="Samples",
908             description="Number of light samples to render for each AA sample",
909             min=1, max=10000,
910             default=1,
911         )
912         cls.max_bounces = IntProperty(
913             name="Max Bounces",
914             description="Maximum number of bounces the light will contribute to the render",
915             min=0, max=1024,
916             default=1024,
917         )
918         cls.use_multiple_importance_sampling = BoolProperty(
919             name="Multiple Importance Sample",
920             description="Use multiple importance sampling for the light, "
921             "reduces noise for area lights and sharp glossy materials",
922             default=True,
923         )
924         cls.is_portal = BoolProperty(
925             name="Is Portal",
926             description="Use this area light to guide sampling of the background, "
927             "note that this will make the light invisible",
928             default=False,
929         )
930
931     @classmethod
932     def unregister(cls):
933         del bpy.types.Light.cycles
934
935
936 class CyclesWorldSettings(bpy.types.PropertyGroup):
937     @classmethod
938     def register(cls):
939         bpy.types.World.cycles = PointerProperty(
940             name="Cycles World Settings",
941             description="Cycles world settings",
942             type=cls,
943         )
944         cls.sampling_method = EnumProperty(
945             name="Sampling method",
946             description="How to sample the background light",
947             items=enum_world_mis,
948             default='AUTOMATIC',
949         )
950         cls.sample_map_resolution = IntProperty(
951             name="Map Resolution",
952             description="Importance map size is resolution x resolution/2; "
953             "higher values potentially produce less noise, at the cost of memory and speed",
954             min=4, max=8192,
955             default=1024,
956         )
957         cls.samples = IntProperty(
958             name="Samples",
959             description="Number of light samples to render for each AA sample",
960             min=1, max=10000,
961             default=1,
962         )
963         cls.max_bounces = IntProperty(
964             name="Max Bounces",
965             description="Maximum number of bounces the background light will contribute to the render",
966             min=0, max=1024,
967             default=1024,
968         )
969         cls.homogeneous_volume = BoolProperty(
970             name="Homogeneous Volume",
971             description="When using volume rendering, assume volume has the same density everywhere"
972             "(not using any textures), for faster rendering",
973             default=False,
974         )
975         cls.volume_sampling = EnumProperty(
976             name="Volume Sampling",
977             description="Sampling method to use for volumes",
978             items=enum_volume_sampling,
979             default='EQUIANGULAR',
980         )
981
982         cls.volume_interpolation = EnumProperty(
983             name="Volume Interpolation",
984             description="Interpolation method to use for volumes",
985             items=enum_volume_interpolation,
986             default='LINEAR',
987         )
988
989     @classmethod
990     def unregister(cls):
991         del bpy.types.World.cycles
992
993
994 class CyclesVisibilitySettings(bpy.types.PropertyGroup):
995     @classmethod
996     def register(cls):
997         bpy.types.Object.cycles_visibility = PointerProperty(
998             name="Cycles Visibility Settings",
999             description="Cycles visibility settings",
1000             type=cls,
1001         )
1002
1003         bpy.types.World.cycles_visibility = PointerProperty(
1004             name="Cycles Visibility Settings",
1005             description="Cycles visibility settings",
1006             type=cls,
1007         )
1008
1009         cls.camera = BoolProperty(
1010             name="Camera",
1011             description="Object visibility for camera rays",
1012             default=True,
1013         )
1014         cls.diffuse = BoolProperty(
1015             name="Diffuse",
1016             description="Object visibility for diffuse reflection rays",
1017             default=True,
1018         )
1019         cls.glossy = BoolProperty(
1020             name="Glossy",
1021             description="Object visibility for glossy reflection rays",
1022             default=True,
1023         )
1024         cls.transmission = BoolProperty(
1025             name="Transmission",
1026             description="Object visibility for transmission rays",
1027             default=True,
1028         )
1029         cls.shadow = BoolProperty(
1030             name="Shadow",
1031             description="Object visibility for shadow rays",
1032             default=True,
1033         )
1034         cls.scatter = BoolProperty(
1035             name="Volume Scatter",
1036             description="Object visibility for volume scatter rays",
1037             default=True,
1038         )
1039
1040     @classmethod
1041     def unregister(cls):
1042         del bpy.types.Object.cycles_visibility
1043         del bpy.types.World.cycles_visibility
1044
1045
1046 class CyclesMeshSettings(bpy.types.PropertyGroup):
1047     @classmethod
1048     def register(cls):
1049         bpy.types.Mesh.cycles = PointerProperty(
1050             name="Cycles Mesh Settings",
1051             description="Cycles mesh settings",
1052             type=cls,
1053         )
1054         bpy.types.Curve.cycles = PointerProperty(
1055             name="Cycles Mesh Settings",
1056             description="Cycles mesh settings",
1057             type=cls,
1058         )
1059         bpy.types.MetaBall.cycles = PointerProperty(
1060             name="Cycles Mesh Settings",
1061             description="Cycles mesh settings",
1062             type=cls,
1063         )
1064
1065     @classmethod
1066     def unregister(cls):
1067         del bpy.types.Mesh.cycles
1068         del bpy.types.Curve.cycles
1069         del bpy.types.MetaBall.cycles
1070
1071
1072 class CyclesObjectSettings(bpy.types.PropertyGroup):
1073     @classmethod
1074     def register(cls):
1075         bpy.types.Object.cycles = PointerProperty(
1076             name="Cycles Object Settings",
1077             description="Cycles object settings",
1078             type=cls,
1079         )
1080
1081         cls.use_motion_blur = BoolProperty(
1082             name="Use Motion Blur",
1083             description="Use motion blur for this object",
1084             default=True,
1085         )
1086
1087         cls.use_deform_motion = BoolProperty(
1088             name="Use Deformation Motion",
1089             description="Use deformation motion blur for this object",
1090             default=True,
1091         )
1092
1093         cls.motion_steps = IntProperty(
1094             name="Motion Steps",
1095             description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))",
1096             min=1, soft_max=8,
1097             default=1,
1098         )
1099
1100         cls.use_camera_cull = BoolProperty(
1101             name="Use Camera Cull",
1102             description="Allow this object and its duplicators to be culled by camera space culling",
1103             default=False,
1104         )
1105
1106         cls.use_distance_cull = BoolProperty(
1107             name="Use Distance Cull",
1108             description="Allow this object and its duplicators to be culled by distance from camera",
1109             default=False,
1110         )
1111
1112         cls.use_adaptive_subdivision = BoolProperty(
1113             name="Use Adaptive Subdivision",
1114             description="Use adaptive render time subdivision",
1115             default=False,
1116         )
1117
1118         cls.dicing_rate = FloatProperty(
1119             name="Dicing Scale",
1120             description="Multiplier for scene dicing rate (located in the Geometry Panel)",
1121             min=0.1, max=1000.0, soft_min=0.5,
1122             default=1.0,
1123         )
1124
1125         cls.is_shadow_catcher = BoolProperty(
1126             name="Shadow Catcher",
1127             description="Only render shadows on this object, for compositing renders into real footage",
1128             default=False,
1129         )
1130
1131         cls.is_holdout = BoolProperty(
1132             name="Holdout",
1133             description="Render objects as a holdout or matte, creating a "
1134             "hole in the image with zero alpha, to fill out in "
1135             "compositing with real footange or another render",
1136             default=False,
1137         )
1138
1139     @classmethod
1140     def unregister(cls):
1141         del bpy.types.Object.cycles
1142
1143
1144 class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
1145     @classmethod
1146     def register(cls):
1147         bpy.types.Scene.cycles_curves = PointerProperty(
1148             name="Cycles Hair Rendering Settings",
1149             description="Cycles hair rendering settings",
1150             type=cls,
1151         )
1152         cls.primitive = EnumProperty(
1153             name="Primitive",
1154             description="Type of primitive used for hair rendering",
1155             items=enum_curve_primitives,
1156             default='LINE_SEGMENTS',
1157         )
1158         cls.shape = EnumProperty(
1159             name="Shape",
1160             description="Form of hair",
1161             items=enum_curve_shape,
1162             default='THICK',
1163         )
1164         cls.cull_backfacing = BoolProperty(
1165             name="Cull Back-faces",
1166             description="Do not test the back-face of each strand",
1167             default=True,
1168         )
1169         cls.use_curves = BoolProperty(
1170             name="Use Cycles Hair Rendering",
1171             description="Activate Cycles hair rendering for particle system",
1172             default=True,
1173         )
1174         cls.resolution = IntProperty(
1175             name="Resolution",
1176             description="Resolution of generated mesh",
1177             min=3, max=64,
1178             default=3,
1179         )
1180         cls.minimum_width = FloatProperty(
1181             name="Minimal width",
1182             description="Minimal pixel width for strands (0 - deactivated)",
1183             min=0.0, max=100.0,
1184             default=0.0,
1185         )
1186         cls.maximum_width = FloatProperty(
1187             name="Maximal width",
1188             description="Maximum extension that strand radius can be increased by",
1189             min=0.0, max=100.0,
1190             default=0.1,
1191         )
1192         cls.subdivisions = IntProperty(
1193             name="Subdivisions",
1194             description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
1195             min=0, max=24,
1196             default=4,
1197         )
1198
1199     @classmethod
1200     def unregister(cls):
1201         del bpy.types.Scene.cycles_curves
1202
1203
1204 def update_render_passes(self, context):
1205     scene = context.scene
1206     rd = scene.render
1207     view_layer = context.view_layer
1208     view_layer.update_render_passes()
1209
1210
1211 class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
1212     @classmethod
1213     def register(cls):
1214         bpy.types.ViewLayer.cycles = PointerProperty(
1215             name="Cycles ViewLayer Settings",
1216             description="Cycles ViewLayer Settings",
1217             type=cls,
1218         )
1219         cls.pass_debug_bvh_traversed_nodes = BoolProperty(
1220             name="Debug BVH Traversed Nodes",
1221             description="Store Debug BVH Traversed Nodes pass",
1222             default=False,
1223             update=update_render_passes,
1224         )
1225         cls.pass_debug_bvh_traversed_instances = BoolProperty(
1226             name="Debug BVH Traversed Instances",
1227             description="Store Debug BVH Traversed Instances pass",
1228             default=False,
1229             update=update_render_passes,
1230         )
1231         cls.pass_debug_bvh_intersections = BoolProperty(
1232             name="Debug BVH Intersections",
1233             description="Store Debug BVH Intersections",
1234             default=False,
1235             update=update_render_passes,
1236         )
1237         cls.pass_debug_ray_bounces = BoolProperty(
1238             name="Debug Ray Bounces",
1239             description="Store Debug Ray Bounces pass",
1240             default=False,
1241             update=update_render_passes,
1242         )
1243         cls.pass_debug_render_time = BoolProperty(
1244             name="Debug Render Time",
1245             description="Render time in milliseconds per sample and pixel",
1246             default=False,
1247             update=update_render_passes,
1248         )
1249         cls.use_pass_volume_direct = BoolProperty(
1250             name="Volume Direct",
1251             description="Deliver direct volumetric scattering pass",
1252             default=False,
1253             update=update_render_passes,
1254         )
1255         cls.use_pass_volume_indirect = BoolProperty(
1256             name="Volume Indirect",
1257             description="Deliver indirect volumetric scattering pass",
1258             default=False,
1259             update=update_render_passes,
1260         )
1261
1262         cls.use_denoising = BoolProperty(
1263             name="Use Denoising",
1264             description="Denoise the rendered image",
1265             default=False,
1266             update=update_render_passes,
1267         )
1268         cls.denoising_diffuse_direct = BoolProperty(
1269             name="Diffuse Direct",
1270             description="Denoise the direct diffuse lighting",
1271             default=True,
1272         )
1273         cls.denoising_diffuse_indirect = BoolProperty(
1274             name="Diffuse Indirect",
1275             description="Denoise the indirect diffuse lighting",
1276             default=True,
1277         )
1278         cls.denoising_glossy_direct = BoolProperty(
1279             name="Glossy Direct",
1280             description="Denoise the direct glossy lighting",
1281             default=True,
1282         )
1283         cls.denoising_glossy_indirect = BoolProperty(
1284             name="Glossy Indirect",
1285             description="Denoise the indirect glossy lighting",
1286             default=True,
1287         )
1288         cls.denoising_transmission_direct = BoolProperty(
1289             name="Transmission Direct",
1290             description="Denoise the direct transmission lighting",
1291             default=True,
1292         )
1293         cls.denoising_transmission_indirect = BoolProperty(
1294             name="Transmission Indirect",
1295             description="Denoise the indirect transmission lighting",
1296             default=True,
1297         )
1298         cls.denoising_subsurface_direct = BoolProperty(
1299             name="Subsurface Direct",
1300             description="Denoise the direct subsurface lighting",
1301             default=True,
1302         )
1303         cls.denoising_subsurface_indirect = BoolProperty(
1304             name="Subsurface Indirect",
1305             description="Denoise the indirect subsurface lighting",
1306             default=True,
1307         )
1308         cls.denoising_strength = FloatProperty(
1309             name="Denoising Strength",
1310             description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
1311             min=0.0, max=1.0,
1312             default=0.5,
1313         )
1314         cls.denoising_feature_strength = FloatProperty(
1315             name="Denoising Feature Strength",
1316             description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
1317             min=0.0, max=1.0,
1318             default=0.5,
1319         )
1320         cls.denoising_radius = IntProperty(
1321             name="Denoising Radius",
1322             description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
1323             min=1, max=25,
1324             default=8,
1325         )
1326         cls.denoising_relative_pca = BoolProperty(
1327             name="Relative filter",
1328             description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
1329             default=False,
1330         )
1331         cls.denoising_store_passes = BoolProperty(
1332             name="Store denoising passes",
1333             description="Store the denoising feature passes and the noisy image",
1334             default=False,
1335             update=update_render_passes,
1336         )
1337
1338     @classmethod
1339     def unregister(cls):
1340         del bpy.types.ViewLayer.cycles
1341
1342
1343 class CyclesDeviceSettings(bpy.types.PropertyGroup):
1344     @classmethod
1345     def register(cls):
1346         cls.id = StringProperty(name="ID")
1347         cls.name = StringProperty(name="Name")
1348         cls.use = BoolProperty(name="Use", default=True)
1349         cls.type = EnumProperty(name="Type", items=enum_device_type, default='CUDA')
1350
1351
1352 class CyclesPreferences(bpy.types.AddonPreferences):
1353     bl_idname = __package__
1354
1355     def get_device_types(self, context):
1356         import _cycles
1357         has_cuda, has_opencl = _cycles.get_device_types()
1358         list = [('NONE', "None", "Don't use compute device", 0)]
1359         if has_cuda:
1360             list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
1361         if has_opencl:
1362             list.append(('OPENCL', "OpenCL", "Use OpenCL for GPU acceleration", 2))
1363         return list
1364
1365     compute_device_type: EnumProperty(
1366         name="Compute Device Type",
1367         description="Device to use for computation (rendering with Cycles)",
1368         items=get_device_types,
1369     )
1370
1371     devices: bpy.props.CollectionProperty(type=CyclesDeviceSettings)
1372
1373     def find_existing_device_entry(self, device):
1374         for device_entry in self.devices:
1375             if device_entry.id == device[2] and device_entry.type == device[1]:
1376                 return device_entry
1377         return None
1378
1379     def update_device_entries(self, device_list):
1380         for device in device_list:
1381             if not device[1] in {'CUDA', 'OPENCL', 'CPU'}:
1382                 continue
1383             # Try to find existing Device entry
1384             entry = self.find_existing_device_entry(device)
1385             if not entry:
1386                 # Create new entry if no existing one was found
1387                 entry = self.devices.add()
1388                 entry.id = device[2]
1389                 entry.name = device[0]
1390                 entry.type = device[1]
1391                 entry.use = entry.type != 'CPU'
1392             elif entry.name != device[0]:
1393                 # Update name in case it changed
1394                 entry.name = device[0]
1395
1396     def get_devices(self):
1397         import _cycles
1398         # Layout of the device tuples: (Name, Type, Persistent ID)
1399         device_list = _cycles.available_devices()
1400         # Make sure device entries are up to date and not referenced before
1401         # we know we don't add new devices. This way we guarantee to not
1402         # hold pointers to a resized array.
1403         self.update_device_entries(device_list)
1404         # Sort entries into lists
1405         cuda_devices = []
1406         opencl_devices = []
1407         cpu_devices = []
1408         for device in device_list:
1409             entry = self.find_existing_device_entry(device)
1410             if entry.type == 'CUDA':
1411                 cuda_devices.append(entry)
1412             elif entry.type == 'OPENCL':
1413                 opencl_devices.append(entry)
1414             elif entry.type == 'CPU':
1415                 cpu_devices.append(entry)
1416         # Extend all GPU devices with CPU.
1417         cuda_devices.extend(cpu_devices)
1418         opencl_devices.extend(cpu_devices)
1419         return cuda_devices, opencl_devices
1420
1421     def get_num_gpu_devices(self):
1422         import _cycles
1423         device_list = _cycles.available_devices()
1424         num = 0
1425         for device in device_list:
1426             if device[1] != self.compute_device_type:
1427                 continue
1428             for dev in self.devices:
1429                 if dev.use and dev.id == device[2]:
1430                     num += 1
1431         return num
1432
1433     def has_active_device(self):
1434         return self.get_num_gpu_devices() > 0
1435
1436     def draw_impl(self, layout, context):
1437         layout.label(text="Cycles Compute Device:")
1438         layout.row().prop(self, "compute_device_type", expand=True)
1439
1440         cuda_devices, opencl_devices = self.get_devices()
1441         row = layout.row()
1442
1443         if self.compute_device_type == 'CUDA' and cuda_devices:
1444             box = row.box()
1445             for device in cuda_devices:
1446                 box.prop(device, "use", text=device.name)
1447
1448         if self.compute_device_type == 'OPENCL' and opencl_devices:
1449             box = row.box()
1450             for device in opencl_devices:
1451                 box.prop(device, "use", text=device.name)
1452
1453     def draw(self, context):
1454         self.draw_impl(self.layout, context)
1455
1456
1457 def register():
1458     bpy.utils.register_class(CyclesRenderSettings)
1459     bpy.utils.register_class(CyclesCameraSettings)
1460     bpy.utils.register_class(CyclesMaterialSettings)
1461     bpy.utils.register_class(CyclesLightSettings)
1462     bpy.utils.register_class(CyclesWorldSettings)
1463     bpy.utils.register_class(CyclesVisibilitySettings)
1464     bpy.utils.register_class(CyclesMeshSettings)
1465     bpy.utils.register_class(CyclesObjectSettings)
1466     bpy.utils.register_class(CyclesCurveRenderSettings)
1467     bpy.utils.register_class(CyclesDeviceSettings)
1468     bpy.utils.register_class(CyclesPreferences)
1469     bpy.utils.register_class(CyclesRenderLayerSettings)
1470
1471
1472 def unregister():
1473     bpy.utils.unregister_class(CyclesRenderSettings)
1474     bpy.utils.unregister_class(CyclesCameraSettings)
1475     bpy.utils.unregister_class(CyclesMaterialSettings)
1476     bpy.utils.unregister_class(CyclesLightSettings)
1477     bpy.utils.unregister_class(CyclesWorldSettings)
1478     bpy.utils.unregister_class(CyclesMeshSettings)
1479     bpy.utils.unregister_class(CyclesObjectSettings)
1480     bpy.utils.unregister_class(CyclesVisibilitySettings)
1481     bpy.utils.unregister_class(CyclesCurveRenderSettings)
1482     bpy.utils.unregister_class(CyclesDeviceSettings)
1483     bpy.utils.unregister_class(CyclesPreferences)
1484     bpy.utils.unregister_class(CyclesRenderLayerSettings)