updated pyconstraint template from nathan (cessen) which exposed some
bugs with pyconstraints, also added a missing decref from python (wasnt freeing the return value from the settings button).
This commit is contained in:
@@ -3,108 +3,108 @@
|
|||||||
Name: 'Script Constraint'
|
Name: 'Script Constraint'
|
||||||
Blender: 245
|
Blender: 245
|
||||||
Group: 'ScriptTemplate'
|
Group: 'ScriptTemplate'
|
||||||
Tooltip: 'Add a new text for custom constraints'
|
Tooltip: 'Add a new script for custom constraints'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from Blender import Window
|
from Blender import Window
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
script_data = \
|
script_data = \
|
||||||
'''#BPYCONSTRAINT
|
"""#BPYCONSTRAINT
|
||||||
|
'''
|
||||||
""" <------- Start removable description section ----------->
|
PyConstraint template, access this in the "add constraint" scripts submenu.
|
||||||
PyConstraints are text buffers that start with #BPYCONSTRAINT.
|
Add docstring here
|
||||||
|
'''
|
||||||
They must define a doConstraint function. The doConstraint
|
|
||||||
function is called with the matrix of the parent object/posebone
|
|
||||||
as the first argument, the matrix of the target object/posebone as
|
|
||||||
the second, and an ID property that's attached to the current constraint
|
|
||||||
instance. The function then must return a 4x4 Mathutils.Matrix() object.
|
|
||||||
|
|
||||||
They must also define a getSettings function. The getSettings
|
|
||||||
function is called with the ID property that's attached to the current constraint
|
|
||||||
instance. It should create a pupblock using the Blender.Draw module to
|
|
||||||
get/set the relevant values of the ID properties.
|
|
||||||
|
|
||||||
When a constraint needs to have a Target Object/Bone, the USE_TARGET line
|
|
||||||
below must be present. Also, if any special matrix creation needs to be performed
|
|
||||||
for the target, a doTarget function must also be defined.
|
|
||||||
|
|
||||||
Optionally, a doDriver function may be defined. This function is used
|
|
||||||
to get and/or modify settings of the owner and target, and as such, should
|
|
||||||
be used with caution. Under no circumstances, should you modify the transforms
|
|
||||||
of either the owner or the target in this function, as they will either have
|
|
||||||
no effect, or will result in other things not being updated correctly. Therefore,
|
|
||||||
it should be used sparringly.
|
|
||||||
|
|
||||||
<------- End removable description section -----------> """
|
|
||||||
|
|
||||||
# Add a licence here if you wish to re-distribute, we recommend the GPL
|
|
||||||
|
|
||||||
# uncomment the following line if Target access is wanted
|
|
||||||
"""
|
|
||||||
USE_TARGET = True
|
|
||||||
"""
|
|
||||||
|
|
||||||
import Blender
|
import Blender
|
||||||
from Blender import Draw
|
from Blender import Draw
|
||||||
from Blender import Mathutils
|
from Blender import Mathutils
|
||||||
from math import *
|
import math
|
||||||
|
|
||||||
# this function is called to evaluate the constraint
|
USE_TARGET = True
|
||||||
# inputmatrix: (Matrix) copy of owner's worldspace matrix
|
|
||||||
# targetmatrix: (Matrix) copy of target's worldspace matrix (where applicable)
|
|
||||||
# idproperty: (IDProperties) wrapped data referring to this
|
|
||||||
# constraint instance's idproperties
|
|
||||||
def doConstraint(inputmatrix, targetmatrix, idproperty):
|
|
||||||
# must return a 4x4 matrix (owner's new matrix)
|
|
||||||
return inputmatrix;
|
|
||||||
|
|
||||||
# this function draws a pupblock that lets the user set
|
|
||||||
# the values of custom settings the constraint defines
|
|
||||||
# idprop: (IDProperties) wrapped data referring to this
|
|
||||||
# constraint instance's idproperties
|
|
||||||
# You MUST use a pupblock. There are errors if you try to use the UIBlock ones.
|
|
||||||
def getSettings(idproperty):
|
|
||||||
pass;
|
|
||||||
|
|
||||||
|
|
||||||
# this optional function performs special actions that only require
|
|
||||||
# access to the target data - calculation of special information
|
|
||||||
# targetobject: (Object) wrapped data referring to the target object
|
|
||||||
# subtarget: (String/PoseChannel)
|
|
||||||
# - If the target is a PoseChannel in an armature, then this
|
|
||||||
# is a wrapped copy of that PoseChannel.
|
|
||||||
# - Otherwise, this field will either be an empty string or the
|
|
||||||
# name of the vertex group
|
|
||||||
# targetmatrix: (Matrix) matrix that will be used as the target matrix
|
|
||||||
# idprop: (IDProperties) wrapped data referring to this
|
|
||||||
# constraint instance's idproperties
|
|
||||||
"""
|
|
||||||
def doTarget (targetobject, subtarget, targetmatix, idproperty):
|
|
||||||
# return a 4x4 matrix (which acts as the matrix of the target)
|
|
||||||
return targetmatrix;
|
|
||||||
"""
|
|
||||||
|
|
||||||
# This optional function is used to modify/get values on the owner and the
|
|
||||||
# target for creating certain setups. It should be used sparingly
|
|
||||||
# ownerobject: (Object) wrapped data referring to the owning object
|
|
||||||
# subowner: (PoseChannel) wrapped data referring to the PoseChannel that
|
|
||||||
# owns the constraint (where applicable)
|
|
||||||
# target: (Object) wrapped data referring to the target
|
|
||||||
# subtarget: (String/PoseChannel)
|
|
||||||
# - If the target is a PoseChannel in an armature, then this
|
|
||||||
# is a wrapped copy of that PoseChannel.
|
|
||||||
# - Otherwise, this field will either be an empty string or the
|
|
||||||
# name of the vertex group
|
|
||||||
"""
|
|
||||||
def doDriver (ownerobject, subowner, targetobject, subtarget, idproperty):
|
|
||||||
pass;
|
|
||||||
"""
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
This function is called to evaluate the constraint
|
||||||
|
obmatrix: (Matrix) copy of owner's worldspace matrix
|
||||||
|
targetmatrix: (Matrix) copy of target's worldspace matrix (where applicable)
|
||||||
|
idprop: (IDProperties) wrapped data referring to this
|
||||||
|
constraint instance's idproperties
|
||||||
|
'''
|
||||||
|
def doConstraint(obmatrix, targetmatrix, idprop):
|
||||||
|
# Separate out the tranformation components for easy access.
|
||||||
|
obloc = obmatrix.translationPart() # Translation
|
||||||
|
obrot = obmatrix.toEuler() # Rotation
|
||||||
|
obsca = obmatrix.scalePart() # Scale
|
||||||
|
|
||||||
|
# Define user-settable parameters.\
|
||||||
|
# Must also be defined in getSettings().
|
||||||
|
if not idprop.has_key('user_toggle'): idprop['user_toggle'] = 1
|
||||||
|
if not idprop.has_key('user_slider'): idprop['user_slider'] = 1.0
|
||||||
|
|
||||||
|
|
||||||
|
# Do stuff here, changing obloc, obrot, and obsca.
|
||||||
|
|
||||||
|
|
||||||
|
# Convert back into a matrix for loc, scale, rotation,
|
||||||
|
mtxloc = Mathutils.TranslationMatrix( obloc )
|
||||||
|
mtxrot = obrot.toMatrix().resize4x4()
|
||||||
|
mtxsca = Mathutils.Matrix([obsca[0],0,0,0], [0,obsca[1],0,0], [0,0,obsca[2],0], [0,0,0,1])
|
||||||
|
|
||||||
|
# Recombine the separate elements into a transform matrix.
|
||||||
|
outputmatrix = mtxsca * mtxrot * mtxloc
|
||||||
|
|
||||||
|
# Return the new matrix.
|
||||||
|
return outputmatrix
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
This function manipulates the target matrix prior to sending it to doConstraint()
|
||||||
|
target_object: wrapped data, representing the target object
|
||||||
|
subtarget_bone: wrapped data, representing the subtarget pose-bone (where applicable)
|
||||||
|
target_matrix: (Matrix) the transformation matrix of the target
|
||||||
|
id_properties_of_constraint: (IDProperties) wrapped idproperties
|
||||||
|
'''
|
||||||
|
def doTarget(target_object, subtarget_bone, target_matrix, id_properties_of_constraint):
|
||||||
|
return target_matrix
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
This function draws a pupblock that lets the user set
|
||||||
|
the values of custom settings the constraint defines.
|
||||||
|
This function is called when the user presses the settings button.
|
||||||
|
idprop: (IDProperties) wrapped data referring to this
|
||||||
|
constraint instance's idproperties
|
||||||
|
'''
|
||||||
|
def getSettings(idprop):
|
||||||
|
# Define user-settable parameters.
|
||||||
|
# Must also be defined in getSettings().
|
||||||
|
if not idprop.has_key('user_toggle'): idprop['user_toggle'] = 1
|
||||||
|
if not idprop.has_key('user_slider'): idprop['user_slider'] = 1.0
|
||||||
|
|
||||||
|
# create temporary vars for interface
|
||||||
|
utoggle = Draw.Create(idprop['user_toggle'])
|
||||||
|
uslider = Draw.Create(idprop['user_slider'])
|
||||||
|
|
||||||
|
|
||||||
|
# define and draw pupblock
|
||||||
|
block = []
|
||||||
|
block.append("Buttons: ")
|
||||||
|
block.append(("Toggle", utoggle, "This is a toggle button."))
|
||||||
|
block.append("More buttons: ")
|
||||||
|
block.append(("Slider", uslider, 0.0000001, 1000.0, "This is a number field."))
|
||||||
|
|
||||||
|
retval = Draw.PupBlock("Constraint Template", block)
|
||||||
|
|
||||||
|
# update id-property values after user changes settings
|
||||||
|
if (retval):
|
||||||
|
idprop['user_toggle']= utoggle.val
|
||||||
|
idprop['user_slider']= uslider.val
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
new_text = bpy.data.texts.new('pyconstraint_template.py')
|
new_text = bpy.data.texts.new('pyconstraint_template.py')
|
||||||
new_text.write(script_data)
|
new_text.write(script_data)
|
||||||
bpy.data.texts.active = new_text
|
bpy.data.texts.active = new_text
|
||||||
Window.RedrawAll()
|
Window.RedrawAll()
|
||||||
|
|||||||
@@ -1627,6 +1627,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
|
|||||||
|
|
||||||
/* free temp objects */
|
/* free temp objects */
|
||||||
Py_XDECREF( idprop );
|
Py_XDECREF( idprop );
|
||||||
|
Py_DECREF( retval );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user