I’m new on Add-On development on Blender and on my first steps I would like to mimic the Item transform Panel and simply act on Location. I made a piece of code, but it only works one way. While the Add-On panel update the object location, changing the object location in its properties doesn’t change the Add-On bpy.props.FloatVectorProperty.
I’m quite sure that is a basic and trivial error or misunderstanding but I would like to know if there is a simple way to manage a such simple stuff?
Here the simple code I wrote,
import bpy
bl_info = {
"name": "Test Add-On",
"blender": (4, 1, 1),
"category": "Object",
}
# Update function
def update_o(self, context):
if context.scene.o is None:
return
context.scene.o.location = context.scene.o_loc
# Create Panel into 3DView
class mOPanel(bpy.types.Panel):
bl_label = "oTest"
bl_idname = "OBJECT_PT_oTest"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "object"
bl_version = "0.0.1"
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(context.scene, "o", text='Object')
if context.scene.o is not None:
row = layout.row()
row.prop(context.scene, "o_loc", )
row = layout.separator(type='LINE')
row = layout.label(text=f"v{self.bl_version}")
# Registering and Unregistering Add-On
def register():
bpy.types.Scene.o = bpy.props.PointerProperty(type=bpy.types.Object)
bpy.types.Scene.o_loc = bpy.props.FloatVectorProperty(name="Location", min=-10.0, max=10.0, step=0.5, default=(0.0 ,0.0 ,0.0), options={'ANIMATABLE'}, update=update_o)
bpy.utils.register_class(mOPanel)
def unregister():
del bpy.types.Scene.o
del bpy.types.Scene.o_loc
bpy.utils.unregister_class(mOPanel)
# Start Add-On
if __name__ == "__main__":
register()
If anyone have an idea how to get that simple thinks working both way I take it! I did try get and set options on bpy.props.FloatVectorProperty but I couldn’t get that work either, maybe I missed something somewhere…
Thanks
Because your property is not connected to the location in any way. get and set callbacks is the way to do it. get will ensure your property to always show the value from the object’s location, set will ensure that new value set to your property updates object’s location.
Thanks a lot @Andrej. I thought the good way was setter / getter but I haven’t succeed yesterday when I tried.
The API documentation on this is really not exhaustive. If you do know how to set this up I really appreciate a piece of code
However be careful because it’s prone to cause an infinite loop of updates, object location updates the scene property which updates object location, …
@Andrej , Thanks, but I already read that example and I could get it work in the add-on context.
While o_loc exist in the context.scene Blender console returns me that the key doesn’t exist
For the people who are also stuck on those kind of problem.
When defining a get/set callback for a property, the self argument in those callbacks refers to the owner of the property (in this case, the Scene), not the panel or a separate variable.
The getters and setters should directly access the currently referenced object (self.o) and return or modify its location.
I’d maybe add a clause like if if obj and obj.location != value: obj.location = value as reassigning the same value would cause a re-calculation of depsgraph when nothing should have changed. Just my 2 cents.