0
$\begingroup$

This question has already been asked for blender 2.8, now that I have had an answer I quote the code fragment of @aliasguru's answer

(How to write __annotations__ (scene property) in new scene?)

This works perfectly on blender 2.8, now I'm trying to figure out how to make it work on blender 2.79, but I can't find the right keys to do it. It is simply a matter of copying the props "props" of the scene recorded in a class of PropertyGroup

def my_function(self, context):
    first_scene = bpy.context.scene

    ### new scene creation comes before the loop:
    new_scene= bpy.data.scenes.new("New scene")    
    context.window.scene = new_scene

    ### copy attributes from source to target scene:
    for key in first_scene.scene_prop.__annotations__.keys():
        source_attribute = getattr(first_scene.scene_prop, key)
        setattr(new_scene.scene_prop, key, source_attribute)

the error I get during code execution is:

AttributeError: 'MyclassPropertyGroup' object has no attribute '__annotations__'

Note: Within the class there are properties of type enum, float, int, string, bool

$\endgroup$
1
$\begingroup$

The code given in the linked answer as you rightfully point out only works in Blender 2.80. I cannot find the source at the moment, but I read somewhere that __annotations__ have been added to Blender 2.80 for exactly the reason you are trying to use it: So that a user can conveniently check out custom added properties that came from Add-ons. There is no true replacement for that in Blender 2.79, the feature simply did not exist.

Other methods can get you a long way though. The given code example can be changed to this:

def my_function(self, context):
    first_scene = bpy.context.scene

    ### new scene creation comes before the loop:
    new_scene= bpy.data.scenes.new("New scene")  
    context.window.scene = new_scene

    ### copy attributes from source to target scene:
    for key in first_scene.scene_prop.bl_rna.properties.keys():
        source_attribute = getattr(first_scene.scene_prop, key)

        ### copy attribute only if it can be written
        ### bl_rna.properties returns more props than you defined yourself
        ### one example is 'rna_type', which is write protected
        ### so use the .is_property_readonly() method that each prop offers to check this
        if not first_scene.scene_prop.is_property_readonly(key):
            setattr(new_scene.scene_prop, key, source_attribute)

There are only two major differences here. One is that the property string list is retrieved using .bl_rna.properties.keys(). You will see .bl_rna on most corners of Blender Python, it is a way of inspecting the internals of the current Python object you are dealing with. Most commonly you will then use the properties path from there (as we do in this code example) to get to the custom defined properties.

The problem we are facing now is, we also get additional ones that were created by Blender itself. rna_type is a common one, I've seen others as well though. Some of these properties, like the mentioned rna_type, are write protected. That's where the second change comes in: Your custom scene_prop has a method called .is_property_readonly(), which needs a string passed on to it - the key we just retrieved. So the if-clause makes sure we just try to set the prop if it can be written.

$\endgroup$
  • $\begingroup$ Sorry for the delay, I voted as an answer, because it is very complete and detailed, it works wonderfully, the "If" clause is fundamental otherwise it won't work! Thank you very much for the time you spent on the answer $\endgroup$ – Pastrokkio Oct 2 at 8:46
1
$\begingroup$

You can pass the property reference to the dir() function in order to get the list of properties.

Proof using the Console:

>>> props = C.scene.my_addon_properties
>>> for attr in dir(props):
...    if hasattr(props, attr):
...        print( "props.%s = %s" % (attr, getattr(props, attr)))
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.