Is there any way to save a variable with a string or other data type within a blender .blend scene?
Are you trying this from within a Python operator or from the Blender UI? Both is possible, but the way to get there is different
If you could explain both cases to me, Iād be grateful.
First, adding a prop using the Blender UI:
Go to the Scene tab in the Property Editor, down to the Custom Properties
section, and click Add
. This will by default add a float property. Use the Edit
button to edit the new Property. The thing is that the data type of such a prop can simply be defined by giving it a different value (same as with Python, these props can change type according to the content). So if you type in a custom string, it will become of type String. You can even add a tooltip this way. Final result should look like this in the UI:
You can access this property now using its key: bpy.context.scene['Test']
should in this case yield My Nice Property
. More clean is to use bpy.context.scene.get('Test')
, as this will return None
if the prop does not exist, instead of breaking your script.
Second, using a StringProperty from inside an operator instead:
There is only 2.7 docs available so far: StringProperty(Property) ā Blender 2.79b f4dc9f9d68b - API documentation
However, difference is only in the syntax of the definition within Operators. With Scenes, the definition is identical. To show how to define it, I used the Operator Simple Python Template:
import bpy
from bpy.props import StringProperty
def main(context):
for ob in context.scene.objects:
print(ob)
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
main(context)
return {'FINISHED'}
def register():
bpy.utils.register_class(SimpleOperator)
bpy.types.Scene.Test = StringProperty(default='My Nice Python Defined Prop')
def unregister():
del bpy.types.Scene.Test
bpy.utils.unregister_class(SimpleOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.object.simple_operator()
You can access this prop using bpy.context.scene.Test
In the code above, only three lines are needed for the prop. First, importing StringProperty from bpy.props (not bpy.types!!!) to access the namespace. Second, in the register()
method, adding the property definition to the Scene type. And finally, in unregister()
, deleting it again, to make sure when the Add-on is reloaded or unloaded, the definition is undone.
Worth noting that as soon as a property is attached to an ID datablock (a Scene is such an ID datablock), Blender saves it to the .blend file automatically.
Even after you " del bpy.types.Scene.Test" in the unregister call back?
Yes, this is necessary, as users could load a file with such properties stored, but forgot to enable the Add-on that created them. As soon as you re enable the Add-on, the data can be accessed again
Awesome, thanks for the reply
Another way I found to store information at the scene is this:
bpy.context.scene.collection["yourPropertyName"] = {}
bpy.context.scene.collection["yourPropertyName"] = "hello world"
I think itās the āMaster Collectionā and I think itās the main collection that will always exist in blender in all scenes of blender 2.8 and canāt be removed by the user, so I thought it would be a good place to keep my information.
This is a possibility, yes. Any ID data type can store properties (as a rule of thumb, check the autocomplete of bpy.data.xxx
to see which types support it). Also see https://docs.blender.org/api/blender_python_api_current/info_quickstart.html#custom-properties from the manual, where further examples are provided.
It makes more sense to store it on the scene itself rather than the master collection, unless itās specifically related to collections.
bpy.context.scene["yourPropertyName"] = "hello world"
Is there a singleton object which the user canāt remove to store custom properties globally in 2.80? Scenes can be deleted and there can be many scenes. What some addons in the past did is to store properties in the default scene āSceneā, but itās not reliable nor do I like the approach in general.
If we had an app.handler to monitor blender startup/shutdown events we could store that in addon data rather than relying on a global singleton. Iām always a fan of anything event-driven, personally⦠but thatās just me.
If itās actually addon configuration fine, but what if itās information related to a blend file and not an addon? Also, donāt get addon properties removed if you disable the addon (possibly restart Blender afterwards)?
Oh I see what you mean- dealing with more than one scene (or lack of a scene) in a single blend file
I am trying to store an array in an object.
I do the following:
bpy.context.active_object['my_test_array'] = ['a'] bpy.context.active_object['my_test_array'].append('b')
but once I query the array (bpy.context.active_object[āmy_test_arrayā]) after appending, it never seems to store the new data with append, is this normal or is it a bug?.
Thanks!.
If you look at your python console itās probably throwing an exception, because active_object['my_test_array']
is not actually a list- itās an IDProperty array, and thereās no .append() function for the IDProperty type.
The correct way to handle this would be to create a PropertyGroup.
I would like to know if you think this is a good idea or if for some reason I shouldnāt use it like this:
###################
# __init__.py file:
###################
class Lists:
def __init__(self, name='List', data=[]):
self.name = name
self.data = data
def register():
bpy.types.Scene.test_list = Lists('Test')
def unregister():
del bpy.types.Scene.test_list
#########
# Usage #
#########
bpy.context.scene.test_list.name
bpy.context.scene.test_list.data
bpy.context.scene.test_list.data.append(1)
bpy.context.scene.test_list.data
Ok, it seems that closing and opening blender loses the data saved in the list, but for temporary things it would be ok.
My best solution for now: