I've finally traced down the causes of several of the bugs which caused PyConstraints to work incorrectly (or not at all).
* Freeing is now done using BLI_freelistN inside the pycon_free function, instead of looping through the targets ourselves. This fixes all of those Memblock free: pointer not in list errors.
* BPY_pyconstraint_update now correctly creates/frees the constraint's targets as needed. Previously, it was creating/removing the wrong number of targets. Also, pyconstraints no longer get disabled when using armatures (not bones)
* The panel drawing was also not working right, as there were still some offset issues.
Once again, I've recoded the constraints system. This time, the goals were:
* To make it more future-proof by 'modernising' the coding style. The long functions filled with switch statements, have given way to function-pointers with smaller functions for specific purposes.
* To make it support constraints which use multiple targets more readily that it did. In the past, it was assumed that constraints could only have at most one target.
As a result, a lot of code has been shuffled around, and modified. Also, the subversion number has been bumped up.
Known issues:
* PyConstraints, which were the main motivation for supporting multiple-targets, are currently broken. There are some bimport() error that keeps causing problems. I've also temporarily removed the doDriver support, although it may return in another form soon.
* Constraints BPy-API is currently has a few features which currently don't work yet
* Outliner currently only displays the names of the constraints instead of the fancy subtarget/target/constraint-name display it used to do. What gets displayed here needs further investigation, as the old way was certainly not that great (and is not compatible with the new system too)
this bug is in 2.45 but can work around by setting it manually
---
import sys as pysys
try:
pysys.modules['__main__'].__arm_weakrefs
except:
pysys.modules['__main__'].__arm_weakrefs = {}
---
changed how draw modes work - when displaying textured meshes in editmode, only draw selected edges when "Edge Draw" is not enabled. this makes it easy to see the texture/mapping without edges getting in the way.
This means editmode can draw like UV/Face mode did when "Draw Edges" was disabled.
Also made the active vert/edge/face color themeable, still need to set the default to somthing other then pink.
I've added the ability for PyConstraints to define a function (doDriver) that is able to directly modify values of the owner/target, so that certain setups can be created reliably. Users should take note that this is against the basic concept of what a constraint does, and that under no circumstances may they set the values of any variables controlling the transforms. For more details, check out the information in the PyConstraint template script.
I've also updated PyConstraints to be aware of geometry targets. The script template has been updated with this information.
After just over a week of coding, I've finished doing a major refactor/cleanup of the constraints code. In the process, quite a few old kludges and ugly hacks have been removed. Also, some new features which will greatly benefit riggers have been implemented.
=== What's New ===
* The long-awaited ``ChildOf Constraint'':
This allows you to animate parent influences, and choose which transformation channels the parent affects the child on (i.e. no translation/rotation/scaling). It should be noted that disabling some combinations may not totally work as expected. Also, the 'Set Inverse' and 'Clear Inverse' buttons at the bottom of this constraint's panel set/clear the inverse correction for the parent's effects. Use these to make the owner not stick/be glued to the parent.
* Constraint/Target Evaluation Spaces:
In some constraints, there are now 1-2 combo boxes at the bottom of their panel, which allows you to pick which `co-ordinate space' they are evaluated in. This is much more flexible than the old 'local' options for bones only were.
* Action Constraint - Loc/Rot/Size Inputs
The Action Constraint can finally use the target's location/rotation/scaling transforms as input, to control the owner of the constraint. This should work much more reliably than it used to. The target evaluation should now also be more accurate due to the new space conversion stuff.
* Transform - No longer in Crazy Space (TM)
Transforming objects/bones with constraints applied should no longer occur in Crazy Space. They are now correctly inverse-corrected. This also applies to old-style object tracking.
=== General Code Changes ===
* solve_constraints is now in constraints.c. I've removed the old `blend consecutive constraints of same type' junk, which made the code more complex than it needed to be.
* evaluate_constraint is now only passed the constraint, and two matrices. A few unused variables have been removed from here.
* A tempolary struct, bConstraintOb, is now passed to solve_constraints instead of relying on an ugly, static workobject in some cases. This works much better.
* Made the formatting of constraint code consistent
* There's a version patch for older files so that constraint settings are correctly converted to the new system. This is currently done for MajorVersion <= 244, and SubVersion < 3. I've bumped up the subversion to 3 for this purpose. However, with the imminent 2.45 release, this may need to be adjusted accordingly.
* LocEulSizeToMat4 and LocQuatSizeToMat4 now work in the order Size, Rot, Location. I've also added a few other math functions.
* Mat4BlendMat4 is now in arithb. I've modified it's method slightly, to use other arithb functions, instead of its crazy blending scheme.
* Moved some of the RigidBodyJoint constraint's code out of blenkernel, and into src. It shouldn't be setting its target in its data initialisation function based + accessing scene stuff where it was doing so.
=== Future Work ===
* Geometry to act as targets for constraints. A space has been reserved for this already.
* Tidy up UI buttons of constraints
* Error print for getSettings was lacking a newline
* When adding a PyConstraint using Ctrl-Alt-C, the script is now queried to find out whether it uses a target.
At last! The ability to code constraints in Python. This opens up many interesting rigging possibilities, as well as making prototyping constraints easier.
* A PyConstraint script must begin with the line
#BPYCONSTRAINT
* It must also define a doConstraint function, which performs the core actions of the constraint.
* PyConstraints use IDProperties to store custom properties for each PyConstraint instance. The scripter can choose which of these ID-Properties to expose to a user to control the behaviour of the constraint. This must be done using the Draw.PupBlock method.
Credits to Joe Eager (joeedh) for coding the original patch on which this is based. I've made heavy revisions to large parts of the patch.
For more detailed information, and some demo scripts, see the following page:
http://aligorith.googlepages.com/pyconstraints2
Data from Armature.c and logic.c still leaks.
Mostly todo with PyList_Append adding a refcount and the bpython api not decrefing.
Also added some features needed to fix a bug in mesh_clean.py (ob.pinShape and ob.activeShape)
-Adding name "self" to the pydriver's dictionary, so that objects can be easily referenced in their own expressions. For example, the expression:
self.LocY
for the LocX channel of an object would force this object's location in X to be equal to its location in Y. As always, feedback welcomed.
* stopped bpy from importing automaticaly as decieded in the meeting.
* removed Blender.Main, since we agree it will be called bpy, renamed files also.
* updated epydocs from this and last commit.
* updated scripts to use bpy.*, and bugfix's for widgetwizard
----------
Definition of default "bpy" module was decrementing reference count, which
caused assertion errors on Windows. This fixes the problem on Linux; Win
developers please test!
Setup for Armature weak ref list was missing from some places where
we execute py code. This confused the interpreter and gave random
attribute/tuple parse errors.
Changed name of weak ref list to "__arm_weakrefs" to avoid name
collision with user variables.
It looks like the changes for bug
#5000 Changin EditMode in Script wrecks memory
break the python interpreter.
Since this is critical, I have #ifdef'ed those out of
BPY_interface.c and Window.c. Did not touch Armature.c.
The ifdefs are tagged with /* bug 5000 */
This means bug #5000 is back in play. Interesting to note
that according to #5846, only scripts run from the script menu
and not via Alt-P were broken.
[ #5000 ] Changin EditMode in Script wrecks memory
Armatures create weakreferences in __main__.__dict__. When Window.Editmode is called, the weaklist it iterated over and armatures are updated.
I wonder how this survived so long in Blender... (2005/03/09 commit).
Reason was the call to BPY_free_screen_spacehandlers(sc) in kernel,
which was freeing up scripthandlers in a weird way. That call is
really obsolete. The real freeing should go in the del_area() call,
to prevent copying and deleting area in the UI to go wrong.
(Crash happened in testing timeline markers, and holding CTRL+Uparrow
a while...)
Users can write any valid Python expression (that evals to an int or float) inside Blender's gui number buttons (preceded by #) and have them evaluated to their actual int or float value.
Button Evaluation has access to the same modules as PyDrivers.
For example:
#1.0*9-2.3
#ob("Camera").LocZ
#1.0/ob("Cube").LocX
#math.sin(math.pi) -- or simply #m.sin(m.pi)
etc
- Found several places, where people explicitly casted the frame number
to short.
- Fixed the crash in BPY_interface by adding an empty line (to make it
recompile everywhere, make clean doesn't help...)
For the build system maintainers:
Problem was: The change in makesdna changed the position of the
scriptlink structure. BPY_interface.c somehow didn't get recompiled
(not even after a make clean!!!) which triggered crashes on adding
scriptlinks.
exit_usiblender() to finalize Python before main library data was freed.
This solved a somewhat specific sigsegv with pydrivers, but as Ken
Hughes found out (thanks!) caused one with scripts that called Blender.Exit().
Now running scripts (G.main->script) are freed in BPY_end_python()
itself (so before the rest of the library data is freed), before
Py_Finalize(). Works fine in all my tests so far.
The file script.c should become obsolete with this change (I added a
comment about it there). If all is indeed fine, it will be removed
later.
text module when user edits the input text box of any pydriver
(Transform Properties panel, Ipo window).
It's enough to click in and out of a single pydriver's text input box
for the module reloading and also re-evaluation of all pydrivers
available. Maybe this "refreshing" should also be available from a
menu, let's see.
Note for Python fans:
Definitions and redefinitions in a reloaded module are properly handled
in Python, but previously defined data in the module doesn't disappear.
So if you define a function "f" inside a module, import it, then change
the function's name to "g" and reload the module, both "f" and "g" will
be available. This is considered a feature, check reload's documentation:
http://docs.python.org/lib/built-in-funcs.html#l2h-59
wiki with info: http://mediawiki.blender.org/index.php/BlenderDev/PyDrivers
(there are two sample .blends in the patch tracker entry, last link in
the wiki page)
Notes:
In usiblender.c I just made Python exit before the main library gets
freed. I found a situation with pydrivers where py's gc tried to del
objects on exit and their ID's were not valid anymore (so sigsegv).
Ton needs to check the depsgraph part.
For now pydrivers can reference their own object, something normal
ipodrivers can't. This seems to work fine and is quite useful, but if
tests prove the restriction is necessary, we just need to uncomment a
piece of code in EXPP_interface.c, marked with "XXX".
Thanks Ton for the ipodrivers code and adding the hooks for the py part
and Martin for the "Button Python Evaluation" patch from which I started
this one.
Anyone interested, please check the wiki, the .blends (they have
README's) and tell me about any issue.
Its scary to think that a redraw space handeler could run
import os
os.system('rm -rf ~/')
removing all user files, Just by opening the blend file!
This means at least you can opt not to run any python scripts you dont want to..
was found. Restore warm fuzzy msg. Text is now
Looking for installed Python version XXX
followed by either
Got it!
or
'import site' failed; use -v for traceback
No installed Python found.
Only built-in modules are available. Some scripts may not run.
Continuing happily.
And while we are at it, clean up a couple of compiler warnings.
PyDict_SetItemString() with objects that were not properly decrefed
afterwards. Due to the number of places this was used, I added a
wrapper EXPP_dict_set_item_str() to gen_utils.c to handle it.
This started as a scriptlink bug, due to how many times scripts were
being executed I think it just magnified how bad the memory leak in
BPy was. Animating the blend attached with this bug report would cause
memory to grow by about 3MB for every 280 frames. After the patch,
memory did not appear to grow at all (or at least not noticably using
Unix's ps and top utils).
Since many of the PyDict_SetItemString() calls were in initialization
modules I think my tests executed most of the changed code, but would
appreciate script users really giving feedback.
(old code is just "#ifdef"-ed out for now.)
Please give this a try on all platforms and give us feedback on what you
see for your sys.path setting in Blender (run these two lines in text window)
import sys
print sys.path
- #2781, reported by Ed Blake: crash on undo when there were active space handlers. Space Handler script links belong to screen areas, which do not get saved on undo. Thanks Ton for pointing out the function that restores ui pointers gone bad.
- Applied patch #2822 by Ken Hughes for bug #2647 ("Setting a Face UV"), reported by Campbell Barton.
- #3022, reported by Timothy Wakeham: "Blender.BGL.glDrawPixels crashes when drawing more pixels then buffer size". Made glDrawPixels check buffer dimensions.
- #2882, reported by Campbell: crash in nmesh.getMaterials(arg == 0 or 1) when nmesh came from GetRawFromMesh(). Raw nmeshes are not linked to Blender meshes, so the method doesn't support these options (getting mat info from the actual mesh) for it.
- #2817, reported by Tod Koeckeritz: Dir_Depth var was not being decremented in BPY_Menus.c, causing dir depth limits to be reached prematurely.
- #2954, reported by Daniel Holtz: "Python scripts crash hard with valid windows paths". Blender.Load() was not meant for background mode, now it's been update to support it, using BKE_read_file instead of BIF_read_file in this case. Also found another issue with command line scripts using Blender.Load() that could crash Blender: trying to free the Text when it wasn't available anymore (loading a new .blend already removed it). There are still issues with one case, though, causing a crash on start or "Memoryblock winopen: double free" at end, when running a script that is already a Blender Text (only if the script calls Blender.Load, of course). Will investigate.
- #2897: reported by Timothy Wakeham: object.setMaterials was asking the length of a Python list w/o confirming first if the passed obj was really a list.
Thanks all for the help and for being patient (long delay, again).
- Pontus Lidman contributed a new module: Blender.Key + access to key objects from NMesh, Lattice and Curve + docs (thanks and sorry for taking so long to check/commit the patch!)
- Allowing EVENT spacehandlers to call the file selector (scriptlinks in general are not allowed, but this special case should be able to). Requested by Paolo Colombo (thanks!)
- tiny doc update (Ken Hughes pointed an error in the space handlers example)
I didn't have time to update the Key module to follow the current bpython design, will do that later and also test it better than I did.