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