1 # SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
8 # A sorting func for collections (working in-place).
9 # XXX Not optimized at all…
10 # XXX If some items in the collection do not have the sortkey property, they are just ignored…
11 def collection_property_sort(collection
, sortkey
, start_idx
=0):
12 while start_idx
+ 1 < len(collection
):
13 while not hasattr(collection
[start_idx
], sortkey
):
15 if start_idx
+ 1 >= len(collection
):
18 min_prop
= collection
[start_idx
]
19 for i
, prop
in enumerate(collection
[start_idx
+ 1:]):
20 if not hasattr(prop
, sortkey
):
22 if getattr(prop
, sortkey
) < getattr(min_prop
, sortkey
):
24 min_idx
= i
+ start_idx
+ 1
25 collection
.move(min_idx
, start_idx
)
30 def scene_render_copy_settings_update():
31 """Prepare internal data for render_copy_settings (gathering all existing render settings, and scenes)."""
32 current_scene
= getattr(bpy
.context
, "scene", None)
33 if current_scene
is None:
35 cp_sett
= current_scene
.render_copy_settings
37 # Get all available render settings, and update accordingly affected_settings…
39 for prop_container_id
in (('render',), ('cycles',), ('eevee',), ('display', 'shading')):
40 prop_container
= current_scene
41 for pc_id_item
in prop_container_id
:
42 prop_container
= getattr(prop_container
, pc_id_item
, None)
43 if prop_container
is None:
45 if prop_container
is None:
47 for prop
in prop_container
.bl_rna
.properties
:
48 if prop
.identifier
in {'rna_type'}:
52 props
[".".join(prop_container_id
) + "." + prop
.identifier
] = prop
.name
54 for i
, sett
in enumerate(cp_sett
.affected_settings
):
55 if sett
.strid
not in props
:
56 cp_sett
.affected_settings
.remove(i
- corr
)
60 for strid
, name
in props
.items():
61 sett
= cp_sett
.affected_settings
.add()
62 sett
.name
= "{} [{}]".format(name
, strid
)
64 collection_property_sort(cp_sett
.affected_settings
, "name")
66 # Get all available scenes, and update accordingly allowed_scenes…
68 if cp_sett
.filter_scene
:
72 regex
= re
.compile(cp_sett
.filter_scene
)
73 except Exception as e
:
74 print("The filter-scene regex did not compile:\n (%s)." % str(e
))
78 print("Unable to import the re module, regex scene filtering will be disabled!")
80 for scene
in bpy
.data
.scenes
:
81 if scene
== current_scene
: # Exclude current scene!
83 # If a valid filtering regex, only keep scenes matching it.
85 if regex
.match(scene
.name
):
86 scenes
.add(scene
.name
)
88 scenes
.add(scene
.name
)
89 for i
, scene
in enumerate(cp_sett
.allowed_scenes
):
90 if scene
.name
not in scenes
:
91 cp_sett
.allowed_scenes
.remove(i
)
93 scenes
.remove(scene
.name
)
95 sett
= cp_sett
.allowed_scenes
.add()
97 collection_property_sort(cp_sett
.allowed_scenes
, "name")
100 from bpy
.props
import EnumProperty
103 class RenderCopySettingsOPPreset(bpy
.types
.Operator
):
104 """Apply some presets of render settings to copy to other scenes"""
105 bl_idname
= "scene.render_copy_settings_preset"
106 bl_label
= "Render: Copy Settings Preset"
107 bl_description
= "Apply or clear this preset of render settings"
109 bl_option
= {'REGISTER', 'UNDO'}
111 presets
: EnumProperty(items
=(p
.rna_enum
for p
in presets
.presets
),
113 options
={'ENUM_FLAG'})
116 def process_elements(settings
, elts
):
119 for sett
in settings
:
120 if sett
.strid
in elts
:
122 val
= val
and sett
.copy
127 def poll(cls
, context
):
128 return context
.scene
is not None
130 def execute(self
, context
):
131 cp_sett
= context
.scene
.render_copy_settings
132 for p
in presets
.presets
:
133 if p
.rna_enum
[0] in self
.presets
:
134 self
.process_elements(cp_sett
.affected_settings
, p
.elements
)
138 # Real interesting stuff…
140 def do_copy(context
, affected_settings
, allowed_scenes
):
141 def resolve_rnapath_get(bdata
, rna_path_items
):
142 for item
in rna_path_items
:
143 bdata
= getattr(bdata
, item
, None)
148 def resolve_rnapath_set(bdata
, rna_path_items
, value
):
149 bdata
= resolve_rnapath_get(bdata
, rna_path_items
[:-1])
150 setattr(bdata
, rna_path_items
[-1], value
)
152 # Stores various render settings from current scene.
153 p
= {rna_path_items
: resolve_rnapath_get(context
.scene
, rna_path_items
)
154 for rna_path_items
in affected_settings
}
155 # put it in all other (valid) scenes’ render settings!
156 for scene
in bpy
.data
.scenes
:
157 # If scene not in allowed scenes, skip.
158 if scene
.name
not in allowed_scenes
:
160 # Propagate all affected settings.
161 for rna_path_items
, val
in p
.items():
162 resolve_rnapath_set(scene
, rna_path_items
, val
)
165 class RenderCopySettingsOPCopy(bpy
.types
.Operator
):
166 """Copy render settings from current scene to others"""
167 bl_idname
= "scene.render_copy_settings"
168 bl_label
= "Render: Copy Settings"
170 bl_option
= {'REGISTER', 'UNDO'}
173 def poll(cls
, context
):
174 return context
.scene
is not None
176 def execute(self
, context
):
178 cp_sett
= context
.scene
.render_copy_settings
179 affected_settings
= {tuple(sett
.strid
.split(".")) for sett
in cp_sett
.affected_settings
if sett
.copy
}
180 allowed_scenes
= {sce
.name
for sce
in cp_sett
.allowed_scenes
if sce
.allowed
}
181 do_copy(context
, affected_settings
=affected_settings
, allowed_scenes
=allowed_scenes
)
186 RenderCopySettingsOPPreset
,
187 RenderCopySettingsOPCopy
,