Does anyone understand the proper use of the “name” field in Collection Properties?
Here’s an example from the 2.75 documentation: http://www.blender.org/api/blender_python_api_2_75_release/bpy.props.html :
import bpy
# Assign a collection
class SceneSettingItem(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
value = bpy.props.IntProperty(name="Test Prop", default=22)
bpy.utils.register_class(SceneSettingItem)
bpy.types.Scene.my_settings = \
bpy.props.CollectionProperty(type=SceneSettingItem)
# Assume an armature object selected
print("Adding 3 values!")
my_item = bpy.context.scene.my_settings.add()
my_item.name = "Spam"
my_item.value = 1000
my_item = bpy.context.scene.my_settings.add()
my_item.name = "Eggs"
my_item.value = 30
for my_item in bpy.context.scene.my_settings:
print(my_item.name, my_item.value)
That code shows an explicit definition of a “name” property in the SceneSettingItem class.
However, it appears that a “name” field is inherited automatically from the PropertyGroup parent class.
To explore this, I created an addon that creates a collection of PropertyGroup elements without an explicit “name” property and a collection of PropertyGroup elements with an explicit “name” property. Here’s the code:
"""
This program explores the special use of the "name" field in property groups
"""
bl_info = {
"version": "0.1",
"name": "Name Collection Testing",
'author': 'Bob',
"location": "Properties > Scene",
"category": "Blender Experiments"
}
import bpy
from bpy.props import *
# An unnamed Element
class UElementPropertyGroup(bpy.types.PropertyGroup):
s = StringProperty(default="UElement")
# A named Element
class NElementPropertyGroup(bpy.types.PropertyGroup):
name = StringProperty()
s = StringProperty(default="NElement")
class AppPropertyGroup(bpy.types.PropertyGroup):
u_list = CollectionProperty(type=UElementPropertyGroup)
n_list = CollectionProperty(type=NElementPropertyGroup)
def fill_to ( self, num ):
for i in range(num):
e = self.u_list.add()
e.name = "u" + str(i)
e.s = e.name + "_string"
e = self.n_list.add()
e.name = "n" + str(i)
e.s = e.name + "_string"
def register():
print ("Registering ", __name__)
bpy.utils.register_module(__name__)
bpy.types.Scene.app = bpy.props.PointerProperty(type=AppPropertyGroup)
def unregister():
print ("Unregistering ", __name__)
del bpy.types.Scene.app
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()
You can invoke it from the Python console via: >>> C.scene.app.fill_to(3)
The two classes appear to function the same (although I haven’t done any performance testing yet). They both appear to have a “name” field, and they both appear to be indexable by the “name” field:
>>> C.scene.app.u_list[‘u2’].s
>>> C.scene.app.n_list[‘n2’].s
However, when I look at the data blocks, they differ. I find that they both have a “Name” field (yes, capital “N”), but the named version has an additional “name” field (lower case “n”). Changing the element.name value appears to change both fields in the Datablocks, and changing either field in the Datablocks appears to change the element.name value as well.
Here are my 2 questions:
-
Should we define an explicit “name” property (as shown in the documentation example), or is it better to use the “name” that’s automatically generated in the class?
-
Does an explicit “name” property improve or degrade performance?
FYI: Here’s a look at the Datablocks for this example from Blender 2.75. You’ll notice that the u0, u1, and u2 (unnamed) collection elements only have a “Name” field. However, the n0, n1, and n2 (named) collection elements have both a “Name” field and a “name” field.