0
$\begingroup$

FYI, this is based on my old question in previous post Is it possible to use single pointer to assign on multiple modifers' Pointer Properties at once?. Now, for my learning and experiement purpose, I wanted to continue to use same script except adding few new string inside. I've encountered some issues and strugging find solution.

The goal was to get active object (Sphere) simultaneously aligned to curve's origin location after picked up curve with eyedropper.

enter image description here

With this single string that pasted inside blender editor and run test...

bpy.context.view_layer.objects.active.location = bpy.context.view_layer.objects.active.my_curve.location

...It was succesful, the sphere got aligned to curve's origin location.

After adding almost exacly same string inside Panel class (class MOD_PT_Curve(bpy.types.Panel) , It didn't work. I am getting error...

import bpy

def update_my_curve(self, context):
    array = self.modifiers.get("Array")
    if array:
        array.curve = self.my_curve
    curve =  self.modifiers.get("Curve")
    if curve:
        curve.object = self.my_curve


class MOD_PT_Curve(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "PANEL"
    bl_idname = "POINTERTEST"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "PJTX"

    def draw(self, context):
        self.layout.prop(context.active_object, "my_curve")


        ## NEWLY ADDED STRING -------------------------------------
        active_obj = bpy.context.view_layer.objects.active
        picked_curve = bpy.context.view_layer.objects.active.my_curve

        
        active_obj.location = picked_curve.location
        ## -------------------------------------------------------


def register():
    bpy.utils.register_class(MOD_PT_Curve)
    bpy.types.Object.my_curve = bpy.props.PointerProperty(
        type=bpy.types.Object, 
        update=update_my_curve, 
        name="My Curve",
        poll=lambda self, object: object.type == "CURVE",  # Filter only curve objects
        )
        
if __name__ == "__main__":
    register()

...And the error from console show

AttributeError: Writing to ID classes in this context is not allowed: Sphere, Object datablock, error setting Object.location

Yes, I know and I believe it was incorrect way to do this, since I am still learning blender-python. I wasn't sure what other methods I could use to solve this. I need help and your help would be greatly appreciated.

$\endgroup$

1 Answer 1

1
$\begingroup$

Avoid placing heavy loads code in draw()

The code in draw() function will excuite Frequently.

import bpy

def ret_first_curve_md(mds):
    for md in mds:
        if md.type == "CURVE":  return md
    return None

def update_my_curve(self, context):
    print("-- update --")
    if self.my_curve is None:           return   # can't get None.location
    if self.my_curve.type != "CURVE":   return   # can't pick a non "CURVE" object for curve modifier

    obj     = bpy.context.object        # get active object
    mds     = obj.modifiers             # object's modifiers store here
    md      = ret_first_curve_md(mds)   # get first curve modifier

    if md is not None:
        md.object       = self.my_curve
        obj.location    = self.my_curve.location
        print("-- success --")


class MOD_PT_Curve(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "PANEL"
    bl_idname = "POINTERTEST"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "PJTX"

    def draw(self, context):
        self.layout.prop(context.active_object, "my_curve")

def register():
    bpy.utils.register_class(MOD_PT_Curve)
    bpy.types.Object.my_curve = bpy.props.PointerProperty(
        type=bpy.types.Object, 
        update=update_my_curve, 
        name="My Curve",
        poll=lambda self, object: object.type == "CURVE",  # Filter only curve objects
        )
        
if __name__ == "__main__":
    register()
$\endgroup$
5
  • $\begingroup$ Wow! this is so clean and clear. Everything is in order, I can now understand how this work. Thank you very much for this. For me to get better understanding or improve in for loop, function, how to avoid heavy loads in draw() or anything that I need to know how exactly you did, where would you recommend me to learn better? It was hard me to find good steps on blender-python. Once again, thank you for help. $\endgroup$
    – sirrus
    Commented Apr 28, 2022 at 14:21
  • $\begingroup$ If you want to learn python better, there are a lot of tutorial in the internet, even the video. $\endgroup$
    – X Y
    Commented Apr 28, 2022 at 14:50
  • $\begingroup$ Oh yes, I am sure there are a lot of Python tutorials out there. but not the python-blender tutorial together. $\endgroup$
    – sirrus
    Commented Apr 28, 2022 at 15:18
  • $\begingroup$ I think the common way to learn blender api is see the blender API Documentation. docs.blender.org/api/current/index.html $\endgroup$
    – X Y
    Commented Apr 28, 2022 at 15:27
  • $\begingroup$ Thank you... That's something I will look into. $\endgroup$
    – sirrus
    Commented Apr 28, 2022 at 15:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .