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