I am working on a script (2.41 ver) to allow me to create parented bones in mesh edit mode. The idea is for easy and precise placement of bones via the crosshair by highlighting vertices then ‘Shift S’ - ‘Cursor -> Selection’ - run script. So far everything works, but I am new to python programming was wondering if it is possible to access the ‘Shift S’ - ‘Cursor -> Selection’ part from python to streamline the work.
Updated 8-8-06:
The script is working, if anyone is willing to test it.
To use:
- Have a mesh an armature and the script.
- Load and run the script (alt+p in text window).
- Select the armature and press the ‘Get’ button for the ‘Armature’.
- Select the mesh and enter Edit Mode.
- Press the ‘Armature EditMode’ toggle button to ON. (This will remember the old object and editmode, then get the armature in editmode)
- Select a Bone on the armature and press the ‘Get’ button for the ‘Target Bone’. (A popup menu will appear asking if you want to start a new chain or continue with the old one, select ‘Start a new chain’)
7)Press the ‘Armature EditMode’ toggle button to OFF. (This will Return to the old object and editmode) - Select some verts and press ‘Add Bone To Verts’ OR left click a point on the 3dView and press ‘Add Bone’.
AddBone.py
Be a few moments, Too many characters
Code:
import Blender
from Blender.Mathutils import *
from Blender import Draw, BGL
sbone = Draw.Create("Bone")
armature = Draw.Create("Armature")
sstate = 0
toggle = Draw.Create(0)
togState = ''
def cursorToVert():
scn= Blender.Scene.GetCurrent()
ob = scn.getActiveObject()
if not ob or ob.getType() != 'Mesh':
Draw.PupMenu("Please select a mesh.")
return
editmode = Blender.Window.EditMode()
if editmode:
Blender.Window.EditMode(0)
mesh = ob.getData(mesh=1)
vert_sel= [v.co for v in mesh.verts if v.sel]
if not vert_sel:
Draw.PupMenu("No verts selected")
if editmode:
Blender.Window.EditMode(1)
return
vert_multi= 1.0/len(vert_sel)
relative_location= reduce(lambda a,b: (a+b), vert_sel) * vert_multi
relative_location.resize4D()
absolute_location = relative_location*ob.matrixWorld
Blender.Window.SetCursorPos(absolute_location[0:3])
Blender.Window.Redraw()
if editmode:
Blender.Window.EditMode(1)
return(1)
def CursorPosition2ArmatureAxis_Translation():
global armature
ArmPos = Blender.Object.Get(armature.val).getLocation('worldspace')
CurPos = Blender.Window.GetCursorPos()
CurPosRelative2ArmPos = Vector(CurPos)-Vector(ArmPos)
ArmObject = Blender.Object.Get(armature.val)
ArmMatrixCopy = Matrix(ArmObject.getMatrix())
return(CurPosRelative2ArmPos*ArmMatrixCopy.invert())
def Bone2VertCaller():
in_editmode = Blender.Window.EditMode()
object = Blender.Scene.GetCurrent().getActiveObject()
if not object or object.getType() != 'Mesh':
Draw.PupMenu("Please select a mesh.")
return
elif in_editmode:
if cursorToVert():
add_bone(1)
else:
question = Draw.PupMenu("OK?%t|Must be in Editmode, Enter Editmode? %x1")
if question == 1:
Blender.Window.EditMode(1)
def ArmatureSelect():
object = Blender.Scene.GetCurrent().getActiveObject()
if not object or object.getType() != 'Armature':
Draw.PupMenu("Please select an armature.")
return
armature.val = Blender.Object.GetSelected()[0].getName()
def add_bone(AD):
global armature, bone, sstate
in_editmode = Blender.Window.EditMode()
scnobjs = Blender.Scene.GetCurrent().getChildren()
for obj in scnobjs:
if armature.val == obj.name:
armatureName = obj.getData(1)
arm = Blender.Armature.Get(armatureName)
if not arm:
Draw.PupMenu("'add_bone(AD)' Armature not in scene")
return
boneName = sbone.val
parentBone = sbone.val
bone_name_list = []
i = 0
for name, bone in arm.bones.items():
bone_name_list.append(name)
while boneName in bone_name_list:
parentBone = boneName
i=i+1
boneName = sbone.val
boneName = boneName + '.' + str(i)
if sstate:
parentBone = sbone.val
sstate = 0
if in_editmode:
Blender.Window.EditMode(0)
arm.makeEditable()
if AD:
eb = Blender.Armature.Editbone()
eb.roll = 10
eb.parent = arm.bones[parentBone]
eb.tail = CursorPosition2ArmatureAxis_Translation()
eb.options = [Blender.Armature.CONNECTED]
arm.bones[boneName] = eb
else:
if parentBone == sbone.val:
Draw.PupMenu("cannot delete target bone")
else:
del arm.bones[parentBone]
arm.update()
if in_editmode:
Blender.Window.EditMode(1)
else:
Blender.Window.EditMode(1)
Blender.Window.EditMode(0)
return
Selection = ''
OldSelection = ''
OldEditmode = 0
def toggleArmature():
global Selection, OldSelection, OldEditmode
in_editmode = Blender.Window.EditMode()
Selection = Blender.Object.GetSelected()[0]
if toggle.val:
OldSelection = Selection.name[:]
if in_editmode:
OldEditmode = 1
Blender.Window.EditMode(0)
Selection.select(0)
object = Blender.Object.Get(armature.val)
object.select(1)
Blender.Window.EditMode(1)
else:
Selection.select(0)
object = Blender.Object.Get(armature.val)
object.select(1)
Blender.Window.EditMode(1)
else:
if OldSelection:
Blender.Window.EditMode(0)
object = Blender.Object.Get(armature.val)
object.select(0)
object = Blender.Object.Get(OldSelection)
object.select(1)
Blender.Window.EditMode(OldEditmode)
OldSelection = ''
Selection = ''
OldEditmode = 0
def getBone():
global sstate
object = Blender.Scene.GetCurrent().getActiveObject()
if not object or object.getType() != 'Armature':
Draw.PupMenu("Please select an armature.")
return(sbone.val)
in_editmode = Blender.Window.EditMode()
if in_editmode:
arm = Blender.Armature.Get(armature.val)
Blender.Window.EditMode(0)
Blender.Window.EditMode(1)
question = Draw.PupMenu("Start a new chain?%x1|Continue with last one. %x2")
if question == 1:
sstate = 1
else:
sstate = 0
for bone in arm.bones.values():
for opt in bone.options:
if 'BONE_SELECTED' == opt.name:
boneSelName = bone.name
return(boneSelName)
else:
Draw.PupMenu("Must be in edit mode")
return(sbone.val)
evtNoEvt = 0
evtTestButton = 1
evtAddBone = 2
evtAddToSelected = 3
evtDeleteBone = 4
evtArmature = 5
evtBone = 6
evtGetArmature = 7
evtGetBone = 8
evtToggleArmEditM = 9
def gui():
global evtNoEvt, evtAddBone, evtAddToSelected, evtDeleteBone, evtArmature
global evtBone, evtGetArmature, evtToggleArmEditM
global armature, sbone, get_bone, toggle, togState
BGL.glRasterPos2i(10,250)
Draw.Text("Press ESC to quit.")
#
BGL.glRasterPos2i(45,215)
Draw.Text('Armature = %s' % armature.val)
Draw.Button("Get", evtGetArmature, 10, 210, 30, 18, "Get selected armature")
toggle = Draw.Toggle("Armature EditMode", evtToggleArmEditM, 10, 185, 160, 18, toggle.val, "Toggle 'armature in editmode' ON or OFF")
if toggle.val: togState = "ON"
else: togState = "OFF"
BGL.glRasterPos2i(180,190)
Draw.Text("%s" % togState)
#
BGL.glRasterPos2i(45,165)
Draw.Text('Target Bone = %s' % sbone.val)
get_bone = Draw.Button("Get", evtGetBone, 10, 160, 30, 18, "Select target bone in armature")
Draw.Button("Add Bone", evtAddBone, 10, 110, 160, 18, "A push button")
BGL.glRasterPos2i(200,115)
Draw.Text("Add a new bone - starting at the end of last bone in target chain")
BGL.glRasterPos2i(200,100)
Draw.Text("and ending at cursor position.")
#
Draw.Button("Add Bone To Verts", evtAddToSelected, 10, 60, 160, 18, "A push button")
BGL.glRasterPos2i(200,65)
Draw.Text("Set cursor to selected vertices and add a bone ending at cursor")
BGL.glRasterPos2i(200,50)
Draw.Text("Must select mesh and be in editmode to work.")
#
Draw.Button("Delete Bone", evtDeleteBone, 10, 10, 160, 18, "A push button")
BGL.glRasterPos2i(200,15)
Draw.Text("Delete last bone in target chain EXEPT the target.")
def event(evt, val):
if evt == Draw.ESCKEY:
stop = Draw.PupMenu("OK?%t|Stop script %x1")
if stop == 1:
Draw.Exit()
return
def buttonEvt(evt):
global evtNoEvt, evtAddBone, evtAddToSelected, evtDeleteBone, evtArmature
global evtBone, evtGetArmature, evtToggleArmEditM
global armature, bone, toggle, togState
if evt == evtAddBone:
add_bone(1)
elif evt == evtAddToSelected:
Bone2VertCaller()
elif evt == evtDeleteBone:
add_bone(0)
elif evt == evtArmature:
pass
elif evt == evtGetArmature:
ArmatureSelect()
elif evt == evtBone:
pass
elif evt == evtGetBone:
sbone.val = getBone()
elif evt == evtToggleArmEditM:
toggleArmature()
elif evt == evtNoEvt:
print "No event."
if evt:
Draw.Redraw()
Draw.Register(gui, event, buttonEvt)