io_scene_vrml2: moved to contrib: T63750
[blender-addons-contrib.git] / amaranth / render / samples_scene.py
1 #  This program is free software; you can redistribute it and/or
2 #  modify it under the terms of the GNU General Public License
3 #  as published by the Free Software Foundation; either version 2
4 #  of the License, or (at your option) any later version.
5 #
6 #  This program is distributed in the hope that it will be useful,
7 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
8 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9 #  GNU General Public License for more details.
10 #
11 #  You should have received a copy of the GNU General Public License
12 #  along with this program; if not, write to the Free Software Foundation,
13 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 """
15 Cycles: Samples per Scene
16
17 When working in production, it's often more convenient to do lighting and
18 compositing in different scenes (so you can later append the comp scene
19     to bring together nodes, settings, lamps, RenderLayers).
20
21 This would lead to work with more than one scene. When doing render tests
22 you want to know at a glance how many samples the other scenes have,
23 without manually switching. This is the idea behind the feature.
24
25 Find it on the Sampling panel, on Render properties.
26 Developed during Caminandes Open Movie Project
27 """
28
29 import bpy
30 from amaranth import utils
31 from bpy.props import (
32         BoolProperty,
33         IntProperty,
34         )
35
36
37 class AMTH_RENDER_OT_cycles_samples_percentage_set(bpy.types.Operator):
38
39     """Save the current number of samples per shader as final (gets saved in .blend)"""
40     bl_idname = "scene.amaranth_cycles_samples_percentage_set"
41     bl_label = "Set as Render Samples"
42
43     def execute(self, context):
44         cycles = context.scene.cycles
45         cycles.use_samples_final = True
46
47         context.scene["amth_cycles_samples_final"] = [
48             cycles.diffuse_samples,
49             cycles.glossy_samples,
50             cycles.transmission_samples,
51             cycles.ao_samples,
52             cycles.mesh_light_samples,
53             cycles.subsurface_samples,
54             cycles.volume_samples]
55
56         self.report({"INFO"}, "Render Samples Saved")
57
58         return {"FINISHED"}
59
60
61 class AMTH_RENDER_OT_cycles_samples_percentage(bpy.types.Operator):
62
63     """Set a percentage of the final render samples"""
64     bl_idname = "scene.amaranth_cycles_samples_percentage"
65     bl_label = "Set Render Samples Percentage"
66
67     percent: IntProperty(
68             name="Percentage",
69             description="Percentage to divide render samples by",
70             subtype="PERCENTAGE", default=0
71             )
72
73     def execute(self, context):
74         percent = self.percent
75         cycles = context.scene.cycles
76         cycles_samples_final = context.scene["amth_cycles_samples_final"]
77
78         cycles.use_samples_final = False
79
80         if percent == 100:
81             cycles.use_samples_final = True
82
83         cycles.diffuse_samples = int((cycles_samples_final[0] / 100) * percent)
84         cycles.glossy_samples = int((cycles_samples_final[1] / 100) * percent)
85         cycles.transmission_samples = int(
86             (cycles_samples_final[2] / 100) * percent)
87         cycles.ao_samples = int((cycles_samples_final[3] / 100) * percent)
88         cycles.mesh_light_samples = int(
89             (cycles_samples_final[4] / 100) * percent)
90         cycles.subsurface_samples = int(
91             (cycles_samples_final[5] / 100) * percent)
92         cycles.volume_samples = int((cycles_samples_final[6] / 100) * percent)
93
94         return {"FINISHED"}
95
96
97 def render_cycles_scene_samples(self, context):
98
99     layout = self.layout
100     scene = context.scene
101     render = scene.render
102     if utils.cycles_exists():
103         cscene = scene.cycles
104         list_sampling = scene.amaranth_cycles_list_sampling
105
106     # Set Render Samples
107     if utils.cycles_exists() and cscene.progressive == "BRANCHED_PATH":
108         layout.separator()
109         split = layout.split()
110         col = split.column()
111
112         col.operator(
113             AMTH_RENDER_OT_cycles_samples_percentage_set.bl_idname,
114             text="%s" %
115             "Set as Render Samples" if cscene.use_samples_final else "Set New Render Samples",
116             icon="%s" %
117             "PINNED" if cscene.use_samples_final else "UNPINNED")
118
119         col = split.column()
120         row = col.row(align=True)
121         row.enabled = True if scene.get("amth_cycles_samples_final") else False
122
123         row.operator(
124             AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
125             text="100%").percent = 100
126         row.operator(
127             AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
128             text="75%").percent = 75
129         row.operator(
130             AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
131             text="50%").percent = 50
132         row.operator(
133             AMTH_RENDER_OT_cycles_samples_percentage.bl_idname,
134             text="25%").percent = 25
135
136     # List Samples
137     if (len(scene.render.layers) > 1) or (len(bpy.data.scenes) > 1):
138
139         box = layout.box()
140         row = box.row(align=True)
141         col = row.column(align=True)
142
143         row = col.row(align=True)
144         row.alignment = "LEFT"
145         row.prop(scene, "amaranth_cycles_list_sampling",
146                  icon="%s" % "TRIA_DOWN" if list_sampling else "TRIA_RIGHT",
147                  emboss=False)
148
149     if list_sampling:
150         if len(scene.render.layers) == 1 and render.layers[0].samples == 0:
151             pass
152         else:
153             col.separator()
154             col.label(text="RenderLayers:", icon="RENDERLAYERS")
155
156             for rl in scene.render.layers:
157                 row = col.row(align=True)
158                 row.label(text=rl.name, icon="BLANK1")
159                 row.prop(
160                     rl, "samples", text="%s" %
161                     "Samples" if rl.samples > 0 else "Automatic (%s)" %
162                     (cscene.aa_samples if cscene.progressive == "BRANCHED_PATH" else cscene.samples))
163
164         if (len(bpy.data.scenes) > 1):
165             col.separator()
166
167             col.label(text="Scenes:", icon="SCENE_DATA")
168
169             if utils.cycles_exists() and cscene.progressive == "PATH":
170                 for s in bpy.data.scenes:
171                     if s != scene:
172                         row = col.row(align=True)
173                         if s.render.engine == "CYCLES":
174                             cscene = s.cycles
175
176                             row.label(s.name)
177                             row.prop(cscene, "samples", icon="BLANK1")
178                         else:
179                             row.label(
180                                 text="Scene: '%s' is not using Cycles" %
181                                 s.name)
182             else:
183                 for s in bpy.data.scenes:
184                     if s != scene:
185                         row = col.row(align=True)
186                         if s.render.engine == "CYCLES":
187                             cscene = s.cycles
188
189                             row.label(text=s.name, icon="BLANK1")
190                             row.prop(cscene, "aa_samples",
191                                      text="AA Samples")
192                         else:
193                             row.label(
194                                 text="Scene: '%s' is not using Cycles" %
195                                 s.name)
196
197
198 def init():
199     scene = bpy.types.Scene
200     if utils.cycles_exists():
201         scene.amaranth_cycles_list_sampling = bpy.props.BoolProperty(
202             default=False,
203             name="Samples Per:")
204         # Note: add versioning code to adress changes introduced in 2.79.1
205         if bpy.app.version >= (2, 79, 1):
206             from cycles import properties as _cycles_props
207             _cycles_props.CyclesRenderSettings.use_samples_final = BoolProperty(
208                     name="Use Final Render Samples",
209                     description="Use current shader samples as final render samples",
210                     default=False
211                     )
212         else:
213             bpy.types.CyclesRenderSettings.use_samples_final = BoolProperty(
214                     name="Use Final Render Samples",
215                     description="Use current shader samples as final render samples",
216                     default=False
217                     )
218
219
220
221 def clear():
222     wm = bpy.context.window_manager
223     for p in ("amarath_cycles_list_sampling", "use_samples_final"):
224         if p in wm:
225             del wm[p]
226
227
228 def register():
229     init()
230     bpy.utils.register_class(AMTH_RENDER_OT_cycles_samples_percentage)
231     bpy.utils.register_class(AMTH_RENDER_OT_cycles_samples_percentage_set)
232     if utils.cycles_exists():
233         if bpy.app.version >= (2, 79, 1):
234             bpy.types.CYCLES_RENDER_PT_sampling.append(render_cycles_scene_samples)
235         else:
236             bpy.types.CyclesRender_PT_sampling.append(render_cycles_scene_samples)
237
238
239 def unregister():
240     bpy.utils.unregister_class(AMTH_RENDER_OT_cycles_samples_percentage)
241     bpy.utils.unregister_class(AMTH_RENDER_OT_cycles_samples_percentage_set)
242     if utils.cycles_exists():
243         if bpy.app.version >= (2, 79, 1):
244             bpy.types.CYCLES_RENDER_PT_sampling.remove(render_cycles_scene_samples)
245         else:
246             bpy.types.CyclesRender_PT_sampling.remove(render_cycles_scene_samples)
247
248
249     clear()