Fix T92924: Copy Render Settings doesn't work in 3.0.

It's not possible anymore to call an operator from drawing code in most
cases (since it may be called during some init phase where this is
forbidden).

Looks like here the only viable solution is to use a timer for now. :(
This commit is contained in:
Bastien Montagne 2021-11-16 14:18:31 +01:00
parent b69c6fd67e
commit e7c2b215bb
Notes: blender-bot 2023-02-14 18:29:16 +01:00
Referenced by issue #92924, Copy Render Settings doesn't work in 3.0
3 changed files with 67 additions and 75 deletions

View File

@ -21,8 +21,8 @@
bl_info = {
"name": "Copy Render Settings",
"author": "Bastien Montagne",
"version": (1, 0, 0),
"blender": (2, 80, 0),
"version": (1, 1, 0),
"blender": (3, 0, 0),
"location": "Render buttons (Properties window)",
"description": "Allows to copy a selection of render settings "
"from current scene to others.",
@ -56,6 +56,11 @@ from bpy.props import (
classes = data.classes + operator.classes + panel.classes
def scene_render_copy_settings_timer():
operator.scene_render_copy_settings_update()
return 1.0 # Run every second.
def register():
for cls in classes:
bpy.utils.register_class(cls)
@ -63,8 +68,12 @@ def register():
bpy.app.translations.register(__name__, translations.translations_dict)
bpy.app.timers.register(scene_render_copy_settings_timer, persistent=True)
def unregister():
bpy.app.timers.unregister(scene_render_copy_settings_timer)
bpy.app.translations.unregister(__name__)
del bpy.types.Scene.render_copy_settings

View File

@ -21,9 +21,6 @@
import bpy
from . import presets
# These operators are only defined because it seems impossible to directly edit properties from UI code…
# A sorting func for collections (working in-place).
# XXX Not optimized at all…
# XXX If some items in the collection do not have the sortkey property, they are just ignored…
@ -46,74 +43,66 @@ def collection_property_sort(collection, sortkey, start_idx=0):
return collection
class RenderCopySettingsOPPrepare(bpy.types.Operator):
"""Prepare internal data for render_copy_settings (gathering all existing render settings, and scenes)"""
bl_idname = "scene.render_copy_settings_prepare"
bl_label = "Render: Copy Settings Prepare"
bl_option = {'REGISTER'}
def scene_render_copy_settings_update():
"""Prepare internal data for render_copy_settings (gathering all existing render settings, and scenes)."""
current_scene = getattr(bpy.context, "scene", None)
if current_scene is None:
return
cp_sett = current_scene.render_copy_settings
@classmethod
def poll(cls, context):
return context.scene is not None
# Get all available render settings, and update accordingly affected_settings…
props = {}
for prop in current_scene.render.bl_rna.properties:
if prop.identifier in {'rna_type'}:
continue
if prop.is_readonly:
continue
props[prop.identifier] = prop.name
corr = 0
for i, sett in enumerate(cp_sett.affected_settings):
if sett.strid not in props:
cp_sett.affected_settings.remove(i - corr)
corr += 1
else:
del props[sett.strid]
for strid, name in props.items():
sett = cp_sett.affected_settings.add()
sett.name = "{} [{}]".format(name, strid)
sett.strid = strid
collection_property_sort(cp_sett.affected_settings, "name")
def execute(self, context):
cp_sett = context.scene.render_copy_settings
# Get all available render settings, and update accordingly affected_settings…
props = {}
for prop in context.scene.render.bl_rna.properties:
if prop.identifier in {'rna_type'}:
continue
if prop.is_readonly:
continue
props[prop.identifier] = prop.name
corr = 0
for i, sett in enumerate(cp_sett.affected_settings):
if sett.strid not in props:
cp_sett.affected_settings.remove(i - corr)
corr += 1
else:
del props[sett.strid]
for strid, name in props.items():
sett = cp_sett.affected_settings.add()
sett.name = "{} [{}]".format(name, strid)
sett.strid = strid
collection_property_sort(cp_sett.affected_settings, "name")
# Get all available scenes, and update accordingly allowed_scenes…
regex = None
if cp_sett.filter_scene:
# Get all available scenes, and update accordingly allowed_scenes…
regex = None
if cp_sett.filter_scene:
try:
import re
try:
import re
try:
regex = re.compile(cp_sett.filter_scene)
except Exception as e:
self.report({'ERROR_INVALID_INPUT'}, "The filter-scene regex did not compile:\n (%s)." % str(e))
return {'CANCELLED'}
except:
regex = None
self.report({'WARNING'}, "Unable to import the re module, regex scene filtering will be disabled!")
scenes = set()
for scene in bpy.data.scenes:
if scene == bpy.context.scene: # Exclude current scene!
continue
# If a valid filtering regex, only keep scenes matching it.
if regex:
if regex.match(scene.name):
scenes.add(scene.name)
else:
regex = re.compile(cp_sett.filter_scene)
except Exception as e:
print("The filter-scene regex did not compile:\n (%s)." % str(e))
return
except:
regex = None
print("Unable to import the re module, regex scene filtering will be disabled!")
scenes = set()
for scene in bpy.data.scenes:
if scene == current_scene: # Exclude current scene!
continue
# If a valid filtering regex, only keep scenes matching it.
if regex:
if regex.match(scene.name):
scenes.add(scene.name)
for i, scene in enumerate(cp_sett.allowed_scenes):
if scene.name not in scenes:
cp_sett.allowed_scenes.remove(i)
else:
scenes.remove(scene.name)
for scene in scenes:
sett = cp_sett.allowed_scenes.add()
sett.name = scene
collection_property_sort(cp_sett.allowed_scenes, "name")
return {'FINISHED'}
else:
scenes.add(scene.name)
for i, scene in enumerate(cp_sett.allowed_scenes):
if scene.name not in scenes:
cp_sett.allowed_scenes.remove(i)
else:
scenes.remove(scene.name)
for scene in scenes:
sett = cp_sett.allowed_scenes.add()
sett.name = scene
collection_property_sort(cp_sett.allowed_scenes, "name")
from bpy.props import EnumProperty
@ -191,7 +180,6 @@ class RenderCopySettingsOPCopy(bpy.types.Operator):
classes = (
RenderCopySettingsOPPrepare,
RenderCopySettingsOPPreset,
RenderCopySettingsOPCopy,
)

View File

@ -55,11 +55,6 @@ class RENDER_PT_copy_settings(bpy.types.Panel):
layout.operator("scene.render_copy_settings", text="Copy Render Settings")
# This will update affected_settings/allowed_scenes (as this seems
# to be impossible to do it from here…).
if bpy.ops.scene.render_copy_settings_prepare.poll():
bpy.ops.scene.render_copy_settings_prepare()
split = layout.split(factor=0.75)
split.template_list("RENDER_UL_copy_settings", "settings", cp_sett, "affected_settings",
cp_sett, "affected_settings_idx", rows=5)