Hi,
I’m working on the new version of my addon fast path, and I have trouble with setting the path target in the bone constraint panel.
Please, could you help me with ?
I already did it for object, but i can’t for bone.
Visually, this is what I want to achieve in python
[ATTACH=CONFIG]485859[/ATTACH]
and this is the error I get
Traceback (most recent call last):
file"\fast_path.py", line 154, in invoke
attributeerror:‘bpy_prop_collection’ object has no attribute ‘constraints’
[ATTACH=CONFIG]485860[/ATTACH]
The problem is in the line 154.
The point is that I can’t access this operator :
bpy.context.object.pose.bones.constraints[“Follow Path”].target = pathname
the selected bone has its own variable “bonename” defined previously as
bonename = bpy.context.active_bone
and pathname is the variable dealing with the path object.
I tried things like
bpy.context.object.pose.bones[bonename].constraints[“Follow Path”].target = bpy.data.objects[“Path”]
but it makes a loop interpreted as double bpy.context obviously.
also tried
bonename.pose.bones.constraints[“Follow Path”].target = pathname
I think it may be just a syntax issue, but I have not found it
Here is the full code, the ends are in comments because i do step by step debug.
The new bone stuff begins at the #class fastpath_bone
# -*- coding: utf-8 -*-
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "fast_path",
"author": "Laurent Laget",
"version": (0, 5),
"blender": (2, 78, 5),
"location": "Add",
"description": "Create fast_path",
"warning": "",
"wiki_url": "",
"category": "Add",
}
import bpy
def main(context):
for ob in context.scene.objects:
print(ob)
#Declaration of variables
forwardaxe = 'TRACK_NEGATIVE_Y'
upaxe = 'UP_Z'
def pathcreation(forwardaxe,upaxe):
#Get duration
duration = bpy.context.scene.frame_end
#Get the name of the selected object and add a follow path constrain to it
objectname = bpy.context.active_object
bpy.ops.object.constraint_add(type='FOLLOW_PATH')
# Add a curve object , name it, delete vertices and make it ready for shift + right click draw
bpy.ops.curve.primitive_nurbs_path_add()
bpy.context.object.name = "Path"
pathname= bpy.context.active_object
bpy.ops.object.editmode_toggle()
bpy.ops.curve.delete(type='VERT')
#Go back to object mode , set origin and reselect the selected object , push the name of the path in the follow path constraint and animate it
bpy.ops.object.editmode_toggle()
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
bpy.context.scene.objects.active = objectname
bpy.context.object.constraints["Follow Path"].target = pathname
bpy.context.object.constraints["Follow Path"].use_curve_follow = True
#Test if the selected object is different from a camera, and set variables accordingly
if objectname.type != 'CAMERA':
forwardaxe = 'TRACK_NEGATIVE_Y'
upaxe = 'UP_Z'
else:
forwardaxe = 'TRACK_NEGATIVE_Z'
upaxe = 'UP_Y'
#Get specific orientations
bpy.context.object.constraints["Follow Path"].forward_axis = forwardaxe
bpy.context.object.constraints["Follow Path"].up_axis = upaxe
override={'constraint':objectname.constraints["Follow Path"]}
bpy.ops.constraint.followpath_path_animate(override,constraint='Follow Path')
#reselect the path
bpy.context.scene.objects.active = pathname
bpy.context.object.data.path_duration = duration
bpy.ops.object.editmode_toggle()
objectname.location[0] = 0
objectname.location[1] = 0
objectname.location[2] = 0
objectname.rotation_euler[0] = 0
objectname.rotation_euler[1] = 0
objectname.rotation_euler[2] = 0
#Class fastpath
class fastpath(bpy.types.Operator):
"""Create a path for the selected object"""
bl_idname = "object.fastpath"
bl_label = "fastpath"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
pathcreation(forwardaxe,upaxe)
return {'FINISHED'}
#Class fastpath_bone
class fastpath_bone(bpy.types.Operator):
"""Create a path for the selected object"""
bl_idname = "object.fastpath"
bl_label = "fastpath"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
#Get duration
duration = bpy.context.scene.frame_end
#Get the name of the selected object and add a follow path constrain to it
bpy.ops.object.posemode_toggle()
objectname = bpy.context.active_object
bpy.ops.object.posemode_toggle()
print(objectname)
#bpy.ops.object.posemode_toggle()
bonename = bpy.context.active_bone
print(bonename)
bpy.ops.pose.constraint_add(type='FOLLOW_PATH')
bpy.ops.object.posemode_toggle()
# Add a curve object , name it, delete vertices and make it ready for shift + right click draw
bpy.ops.curve.primitive_nurbs_path_add()
bpy.context.object.name = "Path"
pathname= bpy.context.active_object
bpy.ops.object.editmode_toggle()
bpy.ops.curve.delete(type='VERT')
#Go back to object mode , set origin and reselect the selected object , push the name of the path in the follow path constraint and animate it
bpy.ops.object.editmode_toggle()
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
#select bone and Go to pose mode
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = objectname
print(objectname)
bpy.ops.object.posemode_toggle()
bpy.ops.pose.select_all(action='DESELECT')
bonename.select=True
bpy.context.object.pose.bones[bonename].constraints["Follow Path"].target = bpy.data.objects["Path"]
#bpy.context.object.pose.bones.constraints["Follow Path"].target = pathname
# bpy.context.object.pose.bones.constraints["Follow Path"].use_curve_follow = True
#
# #Test if the selected object is different from a camera, and set variables accordingly
# if bonename.type != 'CAMERA':
# forwardaxe = 'TRACK_NEGATIVE_Y'
# upaxe = 'UP_Z'
# else:
# forwardaxe = 'TRACK_NEGATIVE_Z'
# upaxe = 'UP_Y'
#
# #Get specific orientations
# bpy.context.object.constraints["Follow Path"].forward_axis = forwardaxe
# bpy.context.object.constraints["Follow Path"].up_axis = upaxe
#
# override={'constraint':bonename.constraints["Follow Path"]}
# bpy.ops.constraint.followpath_path_animate(override,constraint='Follow Path')
#
# #reselect the path
# bpy.context.scene.objects.active = pathname
# bpy.context.object.data.path_duration = duration
# bpy.ops.object.editmode_toggle()
#
# bonename.location[0] = 0
# bonename.location[1] = 0
# bonename.location[2] = 0
#
# bonename.rotation_euler[0] = 0
# bonename.rotation_euler[1] = 0
# bonename.rotation_euler[2] = 0
return {'FINISHED'}
def menu_item(self, context):
self.layout.operator(fastpath.bl_idname, text="fastpath", icon="PLUGIN")
self.layout.operator(fastpath_bone.bl_idname, text="fastpath_bone", icon="PLUGIN")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_curve_add.append(menu_item)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_curve_add.remove(menu_item)
if __name__ == "__main__":
register()
Thank you for your help