2005-04-10 18:33:19 +00:00
|
|
|
/**
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** BEGIN GPL/BL DUAL 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. The Blender
|
|
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
|
|
* about this.
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#else
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
2005-08-23 18:13:30 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_effect_types.h"
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
#include "DNA_ipo_types.h"
|
|
|
|
#include "DNA_key_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_lattice_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
2005-08-11 02:23:52 +00:00
|
|
|
#include "DNA_modifier_types.h"
|
2007-09-24 11:29:25 +00:00
|
|
|
#include "DNA_nla_types.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "DNA_object_types.h"
|
2005-05-04 12:53:35 +00:00
|
|
|
#include "DNA_object_force.h"
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
#include "DNA_particle_types.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
2005-08-23 18:13:30 +00:00
|
|
|
#include "DNA_space_types.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "DNA_texture_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_property_types.h"
|
|
|
|
#include "DNA_vfont_types.h"
|
|
|
|
#include "DNA_constraint_types.h"
|
2007-07-24 12:15:23 +00:00
|
|
|
#include "DNA_listBase.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_armature.h"
|
|
|
|
#include "BKE_blender.h"
|
2008-01-29 21:01:12 +00:00
|
|
|
#include "BKE_cloth.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_curve.h"
|
2005-05-04 12:53:35 +00:00
|
|
|
#include "BKE_constraint.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_depsgraph.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_displist.h"
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_effect.h"
|
2005-05-04 12:53:35 +00:00
|
|
|
#include "BKE_font.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_ipo.h"
|
|
|
|
#include "BKE_lattice.h"
|
2007-09-24 11:29:25 +00:00
|
|
|
#include "BKE_key.h"
|
|
|
|
#include "BKE_main.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_mball.h"
|
2005-08-23 18:13:30 +00:00
|
|
|
#include "BKE_mesh.h"
|
2005-08-11 02:23:52 +00:00
|
|
|
#include "BKE_modifier.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_object.h"
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
#include "BKE_particle.h"
|
2005-05-04 12:53:35 +00:00
|
|
|
#include "BKE_softbody.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BKE_utildefines.h"
|
2008-02-23 22:46:55 +00:00
|
|
|
#include "BKE_bmesh.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-07-27 10:37:20 +00:00
|
|
|
#include "BIF_editaction.h"
|
|
|
|
#include "BIF_editview.h"
|
|
|
|
#include "BIF_editlattice.h"
|
|
|
|
#include "BIF_editconstraint.h"
|
|
|
|
#include "BIF_editarmature.h"
|
|
|
|
#include "BIF_editmesh.h"
|
2007-09-24 11:29:25 +00:00
|
|
|
#include "BIF_editnla.h"
|
2005-08-23 18:13:30 +00:00
|
|
|
#include "BIF_editsima.h"
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
#include "BIF_editparticle.h"
|
2005-07-27 10:37:20 +00:00
|
|
|
#include "BIF_gl.h"
|
|
|
|
#include "BIF_poseobject.h"
|
2005-12-01 19:04:57 +00:00
|
|
|
#include "BIF_meshtools.h"
|
2005-07-27 10:37:20 +00:00
|
|
|
#include "BIF_mywindow.h"
|
|
|
|
#include "BIF_resources.h"
|
|
|
|
#include "BIF_screen.h"
|
|
|
|
#include "BIF_space.h"
|
|
|
|
#include "BIF_toolbox.h"
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BSE_view.h"
|
2007-11-06 11:41:09 +00:00
|
|
|
#include "BSE_drawipo.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BSE_edit.h"
|
|
|
|
#include "BSE_editipo.h"
|
|
|
|
#include "BSE_editipo_types.h"
|
2007-09-24 11:29:25 +00:00
|
|
|
#include "BSE_editaction_types.h"
|
2005-05-04 12:53:35 +00:00
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
#include "BDR_drawaction.h" // list of keyframes in action
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BDR_editobject.h" // reset_slowparents()
|
2005-12-07 12:36:26 +00:00
|
|
|
#include "BDR_unwrapper.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
#include "BLI_arithb.h"
|
2005-10-30 13:50:42 +00:00
|
|
|
#include "BLI_blenlib.h"
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "BLI_editVert.h"
|
|
|
|
|
2007-10-18 21:47:55 +00:00
|
|
|
#include "editmesh.h"
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
#include "blendef.h"
|
|
|
|
|
|
|
|
#include "mydevice.h"
|
|
|
|
|
|
|
|
extern ListBase editNurb;
|
|
|
|
extern ListBase editelems;
|
|
|
|
|
|
|
|
#include "transform.h"
|
|
|
|
|
2007-07-24 12:15:23 +00:00
|
|
|
/* local function prototype - for Object/Bone Constraints */
|
2007-11-10 02:53:19 +00:00
|
|
|
static short constraints_list_needinv(TransInfo *t, ListBase *list);
|
2005-05-04 12:53:35 +00:00
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* ************************** Functions *************************** */
|
|
|
|
|
|
|
|
static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
|
|
|
|
TransData pivot = *head;
|
|
|
|
TransData *ihead = head;
|
|
|
|
TransData *itail = tail;
|
|
|
|
short connected = t->flag & T_PROP_CONNECTED;
|
|
|
|
|
|
|
|
while (head < tail)
|
|
|
|
{
|
|
|
|
if (connected) {
|
|
|
|
while ((tail->dist >= pivot.dist) && (head < tail))
|
|
|
|
tail--;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
while ((tail->rdist >= pivot.rdist) && (head < tail))
|
|
|
|
tail--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (head != tail)
|
|
|
|
{
|
|
|
|
*head = *tail;
|
|
|
|
head++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connected) {
|
|
|
|
while ((head->dist <= pivot.dist) && (head < tail))
|
|
|
|
head++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
while ((head->rdist <= pivot.rdist) && (head < tail))
|
|
|
|
head++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (head != tail)
|
|
|
|
{
|
|
|
|
*tail = *head;
|
|
|
|
tail--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*head = pivot;
|
|
|
|
if (ihead < head) {
|
|
|
|
qsort_trans_data(t, ihead, head-1);
|
|
|
|
}
|
|
|
|
if (itail > head) {
|
|
|
|
qsort_trans_data(t, head+1, itail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sort_trans_data_dist(TransInfo *t) {
|
|
|
|
TransData *start = t->data;
|
|
|
|
int i = 1;
|
|
|
|
|
|
|
|
while(i < t->total && start->flag & TD_SELECTED) {
|
|
|
|
start++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
qsort_trans_data(t, start, t->data + t->total - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sort_trans_data(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *sel, *unsel;
|
|
|
|
TransData temp;
|
|
|
|
unsel = t->data;
|
|
|
|
sel = t->data;
|
|
|
|
sel += t->total - 1;
|
|
|
|
while (sel > unsel) {
|
|
|
|
while (unsel->flag & TD_SELECTED) {
|
|
|
|
unsel++;
|
|
|
|
if (unsel == sel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (!(sel->flag & TD_SELECTED)) {
|
|
|
|
sel--;
|
|
|
|
if (unsel == sel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
temp = *unsel;
|
|
|
|
*unsel = *sel;
|
|
|
|
*sel = temp;
|
|
|
|
sel--;
|
|
|
|
unsel++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* distance calculated from not-selected vertex to nearest selected vertex
|
|
|
|
warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
|
|
|
|
static void set_prop_dist(TransInfo *t, short with_dist)
|
|
|
|
{
|
|
|
|
TransData *tob;
|
|
|
|
int a;
|
2005-08-23 18:13:30 +00:00
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
for(a=0, tob= t->data; a<t->total; a++, tob++) {
|
|
|
|
|
|
|
|
tob->rdist= 0.0f; // init, it was mallocced
|
|
|
|
|
|
|
|
if((tob->flag & TD_SELECTED)==0) {
|
|
|
|
TransData *td;
|
|
|
|
int i;
|
|
|
|
float dist, vec[3];
|
|
|
|
|
|
|
|
tob->rdist = -1.0f; // signal for next loop
|
|
|
|
|
|
|
|
for (i = 0, td= t->data; i < t->total; i++, td++) {
|
|
|
|
if(td->flag & TD_SELECTED) {
|
|
|
|
VecSubf(vec, tob->center, td->center);
|
|
|
|
Mat3MulVecfl(tob->mtx, vec);
|
2007-04-04 13:18:41 +00:00
|
|
|
dist = Normalize(vec);
|
2005-04-10 18:33:19 +00:00
|
|
|
if (tob->rdist == -1.0f) {
|
|
|
|
tob->rdist = dist;
|
|
|
|
}
|
|
|
|
else if (dist < tob->rdist) {
|
|
|
|
tob->rdist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else break; // by definition transdata has selected items in beginning
|
|
|
|
}
|
|
|
|
if (with_dist) {
|
|
|
|
tob->dist = tob->rdist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************** CONVERSIONS ************************* */
|
|
|
|
|
|
|
|
/* ********************* texture space ********* */
|
|
|
|
|
|
|
|
static void createTransTexspace(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td;
|
|
|
|
Object *ob;
|
|
|
|
ID *id;
|
|
|
|
|
|
|
|
ob= OBACT;
|
2006-12-03 18:30:34 +00:00
|
|
|
|
2007-05-21 18:42:47 +00:00
|
|
|
if (ob==NULL) { // Shouldn't logically happen, but still...
|
2006-12-03 18:30:34 +00:00
|
|
|
t->total = 0;
|
|
|
|
return;
|
|
|
|
}
|
Big Transform Manipulator Merge
*NOTE*: Some UI decision done in this commit will most likely be revised, all flame shall go in /dev/null. Constructive discussions of course welcomed.
This commit merges manipulator orientation selection back in "traditional" transform.
That's how it works:
- The dropdown in the 3D view header is always visible
- The orientation chosen will be used when choosing an axis with MMB and for the *second* key press of X,Y,Z
However, Local orientation doesn't use the one calculated by the manipulator. This is to ensure that multiple object local and armatures in pose still works as before.
- Alt-Space (to change the orientation) works during transform
New Transform orientation: View, using the view axis.
Fixes for the following bugs:
- Constraint projection code "jammed" if input vector was <0,0,0>, reported a couple of times on IRC. Thanks to Basse for the example file.
- Transform on texspace crashed on objects without texspace data (camera, lamp, ...). This was reported in tracker.
- Numinput with lock constraints didn't work correctly. Reported on elysiun
Probably some others that I'm forgetting
I also moved a couple of functions around in an attempt to make things clearer.
2005-07-24 06:25:00 +00:00
|
|
|
|
|
|
|
id= ob->data;
|
|
|
|
if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
|
|
|
|
t->total = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
t->total = 1;
|
|
|
|
td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
|
|
|
|
td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
|
|
|
|
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
VECCOPY(td->center, ob->obmat[3]);
|
|
|
|
td->ob = ob;
|
|
|
|
|
|
|
|
Mat3CpyMat4(td->mtx, ob->obmat);
|
2006-05-14 17:02:56 +00:00
|
|
|
Mat3CpyMat4(td->axismtx, ob->obmat);
|
|
|
|
Mat3Ortho(td->axismtx);
|
2005-04-10 18:33:19 +00:00
|
|
|
Mat3Inv(td->smtx, td->mtx);
|
|
|
|
|
Big Transform Manipulator Merge
*NOTE*: Some UI decision done in this commit will most likely be revised, all flame shall go in /dev/null. Constructive discussions of course welcomed.
This commit merges manipulator orientation selection back in "traditional" transform.
That's how it works:
- The dropdown in the 3D view header is always visible
- The orientation chosen will be used when choosing an axis with MMB and for the *second* key press of X,Y,Z
However, Local orientation doesn't use the one calculated by the manipulator. This is to ensure that multiple object local and armatures in pose still works as before.
- Alt-Space (to change the orientation) works during transform
New Transform orientation: View, using the view axis.
Fixes for the following bugs:
- Constraint projection code "jammed" if input vector was <0,0,0>, reported a couple of times on IRC. Thanks to Basse for the example file.
- Transform on texspace crashed on objects without texspace data (camera, lamp, ...). This was reported in tracker.
- Numinput with lock constraints didn't work correctly. Reported on elysiun
Probably some others that I'm forgetting
I also moved a couple of functions around in an attempt to make things clearer.
2005-07-24 06:25:00 +00:00
|
|
|
if( GS(id->name)==ID_ME) {
|
2005-04-10 18:33:19 +00:00
|
|
|
Mesh *me= ob->data;
|
|
|
|
me->texflag &= ~AUTOSPACE;
|
|
|
|
td->loc= me->loc;
|
|
|
|
td->ext->rot= me->rot;
|
|
|
|
td->ext->size= me->size;
|
|
|
|
}
|
|
|
|
else if( GS(id->name)==ID_CU) {
|
|
|
|
Curve *cu= ob->data;
|
|
|
|
cu->texflag &= ~CU_AUTOSPACE;
|
|
|
|
td->loc= cu->loc;
|
|
|
|
td->ext->rot= cu->rot;
|
|
|
|
td->ext->size= cu->size;
|
|
|
|
}
|
|
|
|
else if( GS(id->name)==ID_MB) {
|
|
|
|
MetaBall *mb= ob->data;
|
|
|
|
mb->texflag &= ~MB_AUTOSPACE;
|
|
|
|
td->loc= mb->loc;
|
|
|
|
td->ext->rot= mb->rot;
|
|
|
|
td->ext->size= mb->size;
|
|
|
|
}
|
|
|
|
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
VECCOPY(td->ext->irot, td->ext->rot);
|
|
|
|
VECCOPY(td->ext->isize, td->ext->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* edge (for crease) ***** */
|
|
|
|
|
|
|
|
static void createTransEdge(TransInfo *t) {
|
|
|
|
TransData *td = NULL;
|
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditEdge *eed;
|
|
|
|
float mtx[3][3], smtx[3][3];
|
|
|
|
int count=0, countsel=0;
|
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
|
|
if(eed->h==0) {
|
|
|
|
if (eed->f & SELECT) countsel++;
|
|
|
|
if (propmode) count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (countsel == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(propmode) {
|
|
|
|
t->total = count;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->total = countsel;
|
|
|
|
}
|
|
|
|
|
|
|
|
td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
|
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
|
|
if(eed->h==0 && (eed->f & SELECT || propmode)) {
|
|
|
|
/* need to set center for center calculations */
|
|
|
|
VecAddf(td->center, eed->v1->co, eed->v2->co);
|
|
|
|
VecMulf(td->center, 0.5f);
|
|
|
|
|
|
|
|
td->loc= NULL;
|
|
|
|
if (eed->f & SELECT)
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
else
|
|
|
|
td->flag= 0;
|
|
|
|
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
2008-02-23 22:46:55 +00:00
|
|
|
if (t->mode == TFM_BWEIGHT) {
|
|
|
|
td->val = &(eed->bweight);
|
|
|
|
td->ival = eed->bweight;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
td->val = &(eed->crease);
|
|
|
|
td->ival = eed->crease;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
td++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* pose mode ************* */
|
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
{
|
2005-10-30 13:50:42 +00:00
|
|
|
bConstraint *con= pchan->constraints.first;
|
|
|
|
|
|
|
|
for(;con; con= con->next) {
|
|
|
|
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
|
|
|
|
bKinematicConstraint *data= con->data;
|
|
|
|
|
|
|
|
if(data->tar==NULL)
|
|
|
|
return data;
|
|
|
|
if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
|
2007-04-06 10:24:14 +00:00
|
|
|
static short apply_targetless_ik(Object *ob)
|
2005-10-30 13:50:42 +00:00
|
|
|
{
|
|
|
|
bPoseChannel *pchan, *parchan, *chanlist[256];
|
|
|
|
bKinematicConstraint *data;
|
2007-04-06 10:24:14 +00:00
|
|
|
int segcount, apply= 0;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
/* now we got a difficult situation... we have to find the
|
|
|
|
target-less IK pchans, and apply transformation to the all
|
|
|
|
pchans that were in the chain */
|
|
|
|
|
|
|
|
for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
|
|
|
|
data= has_targetless_ik(pchan);
|
|
|
|
if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
|
|
|
|
|
|
|
|
/* fill the array with the bones of the chain (armature.c does same, keep it synced) */
|
|
|
|
segcount= 0;
|
|
|
|
|
|
|
|
/* exclude tip from chain? */
|
|
|
|
if(!(data->flag & CONSTRAINT_IK_TIP))
|
|
|
|
parchan= pchan->parent;
|
|
|
|
else
|
|
|
|
parchan= pchan;
|
|
|
|
|
|
|
|
/* Find the chain's root & count the segments needed */
|
|
|
|
for (; parchan; parchan=parchan->parent){
|
|
|
|
chanlist[segcount]= parchan;
|
|
|
|
segcount++;
|
|
|
|
|
|
|
|
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
|
|
|
|
}
|
|
|
|
for(;segcount;segcount--) {
|
|
|
|
Bone *bone;
|
|
|
|
float rmat[4][4], tmat[4][4], imat[4][4];
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
|
|
|
|
/* we put in channel the entire result of rmat= (channel * constraint * IK) */
|
|
|
|
/* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
|
|
|
|
/* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
parchan= chanlist[segcount-1];
|
|
|
|
bone= parchan->bone;
|
2005-11-17 22:07:06 +00:00
|
|
|
bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
if(parchan->parent) {
|
2005-11-05 20:02:04 +00:00
|
|
|
Bone *parbone= parchan->parent->bone;
|
2005-10-30 13:50:42 +00:00
|
|
|
float offs_bone[4][4];
|
|
|
|
|
|
|
|
/* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
|
|
|
|
Mat4CpyMat3(offs_bone, bone->bone_mat);
|
|
|
|
|
|
|
|
/* The bone's root offset (is in the parent's coordinate system) */
|
|
|
|
VECCOPY(offs_bone[3], bone->head);
|
|
|
|
|
|
|
|
/* Get the length translation of parent (length along y axis) */
|
2005-11-05 20:02:04 +00:00
|
|
|
offs_bone[3][1]+= parbone->length;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
/* pose_mat(b-1) * offs_bone */
|
2005-11-05 20:02:04 +00:00
|
|
|
if(parchan->bone->flag & BONE_HINGE) {
|
|
|
|
/* the rotation of the parent restposition */
|
|
|
|
Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
|
|
|
|
|
|
|
|
/* the location of actual parent transform */
|
|
|
|
VECCOPY(rmat[3], offs_bone[3]);
|
|
|
|
offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
|
|
|
|
Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
|
|
|
|
|
|
|
|
Mat4MulMat4(tmat, offs_bone, rmat);
|
|
|
|
}
|
2008-03-04 13:33:19 +00:00
|
|
|
else if(parchan->bone->flag & BONE_NO_SCALE) {
|
|
|
|
Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
|
|
|
|
Mat4Ortho(tmat);
|
|
|
|
}
|
2005-10-31 10:10:01 +00:00
|
|
|
else
|
|
|
|
Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
|
Three new features:
1) Stride Bone
For walkcycles, you could already set an NLA strip to cycle over a path
based on a preset distance value. This cycling happens based on a linear
interpolation, with constant speed.
Not all cycles have a constant speed however, like hopping or jumping.
To ensure a perfect slipping-less foot contact, you now can set a Bone
in an Armature to define the stride. This "Stride Bone" then becomes a
sort-of ruler, a conveyor belt, on which the character walks. When using
the NLA "Use Path" option, it then tries to keep the Stride Bone entirely
motionless on the path, by cancelling out its motion (for the entire
Armature). This means that the animation keys for a Stride Bone have to be
exactly negative of the desired path. Only, at choice, the X,Y or Z Ipo
curve is used for this stride.
Examples:
http://www.blender.org/bf/0001_0040.avi
The top armature shows the actual Action, the bottom armature has been
parented to a Path, using the Stride Bone feature.
http://www.blender.org/bf/0001_0080.avi
Here the Stride Bone has a number of children, creating a ruler to be
used as reference while animating.
Test .blend:
http://www.blender.org/bf/motionblender1.blend
Notes:
- Note that action keys for Bones work local, based on the Bone's
orientation as set in EditMode. Therefore, an Y translation always
goes in the Bone's direction.
- To be able to get a "solvable" stride, the animation curve has
to be inverse evaluated, using a Newton Raphson root solver. That
means you can only create stride curves that keep moving forward, and
cannot return halfway.
- Set the Stride Bone in the Editing Buttons, Bone Panel. You can set
change the name or set the axis in the NLA Window, Strip Properties Panel.
- Files in this commit will move to the blender.org release section.
2) Armature Ghosting
In EditButtons, Armature Panel, you can set an armature to draw ghosts.
The number value denotes the amount of frames that have to be drawn extra
(for the active action!) around the current frame.
Ghosts only evaluate its own Pose, executing it's Actions, Constraints and
IK. No external dependencies are re-evaluated for it.
3) NLA/Action time control
If you click in the NLA window on the action (linked to Object), it makes
sure the Timing as drawn in the Action editor is not corrected for NLA.
If you also set the Object to "Action", this timing will be executed on the
Object as well (not NLA time).
(It's a bit confusing... will make a good doc & maybe review UI!)
2005-11-01 12:44:30 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
Mat4Invert(imat, tmat);
|
2005-07-04 05:16:54 +00:00
|
|
|
}
|
|
|
|
else {
|
2005-10-30 13:50:42 +00:00
|
|
|
Mat4CpyMat3(tmat, bone->bone_mat);
|
|
|
|
|
|
|
|
VECCOPY(tmat[3], bone->head);
|
|
|
|
Mat4Invert(imat, tmat);
|
2005-07-04 05:16:54 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
/* result matrix */
|
|
|
|
Mat4MulMat4(rmat, parchan->pose_mat, imat);
|
2005-07-19 16:12:56 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* apply and decompose, doesn't work for constraints or non-uniform scale well */
|
|
|
|
{
|
|
|
|
float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
Mat3CpyMat4(rmat3, rmat);
|
|
|
|
|
|
|
|
/* quaternion */
|
|
|
|
Mat3ToQuat(rmat3, parchan->quat);
|
|
|
|
|
|
|
|
/* for size, remove rotation */
|
|
|
|
QuatToMat3(parchan->quat, qmat);
|
|
|
|
Mat3Inv(imat, qmat);
|
|
|
|
Mat3MulMat3(smat, rmat3, imat);
|
|
|
|
Mat3ToSize(smat, parchan->size);
|
|
|
|
|
|
|
|
VECCOPY(parchan->loc, rmat[3]);
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
|
2007-04-06 10:24:14 +00:00
|
|
|
apply= 1;
|
2005-10-30 13:50:42 +00:00
|
|
|
data->flag &= ~CONSTRAINT_IK_AUTO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-06 10:24:14 +00:00
|
|
|
return apply;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
|
|
|
|
{
|
|
|
|
Bone *bone= pchan->bone;
|
|
|
|
float pmat[3][3], omat[3][3];
|
2007-07-24 12:15:23 +00:00
|
|
|
float cmat[3][3], tmat[3][3];
|
2005-10-30 13:50:42 +00:00
|
|
|
float vec[3];
|
|
|
|
|
|
|
|
VECCOPY(vec, pchan->pose_mat[3]);
|
|
|
|
VECCOPY(td->center, vec);
|
|
|
|
|
|
|
|
td->ob = ob;
|
|
|
|
td->flag= TD_SELECTED|TD_USEQUAT;
|
2007-11-01 12:55:47 +00:00
|
|
|
if(bone->flag & BONE_HINGE_CHILD_TRANSFORM)
|
|
|
|
td->flag |= TD_NOCENTER;
|
2005-10-30 13:50:42 +00:00
|
|
|
td->protectflag= pchan->protectflag;
|
|
|
|
|
|
|
|
td->loc = pchan->loc;
|
|
|
|
VECCOPY(td->iloc, pchan->loc);
|
|
|
|
|
|
|
|
td->ext->rot= NULL;
|
|
|
|
td->ext->quat= pchan->quat;
|
|
|
|
td->ext->size= pchan->size;
|
|
|
|
|
|
|
|
QUATCOPY(td->ext->iquat, pchan->quat);
|
|
|
|
VECCOPY(td->ext->isize, pchan->size);
|
|
|
|
|
2007-07-24 12:15:23 +00:00
|
|
|
/* proper way to get parent transform + own transform + constraints transform */
|
2005-10-30 13:50:42 +00:00
|
|
|
Mat3CpyMat4(omat, ob->obmat);
|
|
|
|
|
2007-07-24 12:15:23 +00:00
|
|
|
if(pchan->parent) {
|
|
|
|
if(pchan->bone->flag & BONE_HINGE)
|
|
|
|
Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
|
|
|
|
else
|
|
|
|
Mat3CpyMat4(pmat, pchan->parent->pose_mat);
|
|
|
|
|
2007-11-10 02:53:19 +00:00
|
|
|
if (constraints_list_needinv(t, &pchan->constraints)) {
|
2007-07-24 12:15:23 +00:00
|
|
|
Mat3CpyMat4(tmat, pchan->constinv);
|
|
|
|
Mat3Inv(cmat, tmat);
|
2008-01-22 20:59:45 +00:00
|
|
|
Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
|
2007-07-24 12:15:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
|
|
|
|
}
|
|
|
|
else {
|
2007-11-10 02:53:19 +00:00
|
|
|
if (constraints_list_needinv(t, &pchan->constraints)) {
|
2007-07-24 12:15:23 +00:00
|
|
|
Mat3CpyMat4(tmat, pchan->constinv);
|
|
|
|
Mat3Inv(cmat, tmat);
|
2008-01-22 20:59:45 +00:00
|
|
|
Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
|
2007-07-24 12:15:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
|
|
|
|
}
|
|
|
|
|
== Constraints System ==
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
2007-07-15 03:35:37 +00:00
|
|
|
Mat3Inv(td->smtx, td->mtx);
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
/* for axismat we use bone's own transform */
|
|
|
|
Mat3CpyMat4(pmat, pchan->pose_mat);
|
|
|
|
Mat3MulMat3(td->axismtx, omat, pmat);
|
|
|
|
Mat3Ortho(td->axismtx);
|
|
|
|
|
|
|
|
if(t->mode==TFM_BONESIZE) {
|
|
|
|
bArmature *arm= t->poseobj->data;
|
|
|
|
|
|
|
|
if(arm->drawtype==ARM_ENVELOPE) {
|
|
|
|
td->loc= NULL;
|
|
|
|
td->val= &bone->dist;
|
|
|
|
td->ival= bone->dist;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// abusive storage of scale in the loc pointer :)
|
|
|
|
td->loc= &bone->xwidth;
|
|
|
|
VECCOPY (td->iloc, td->loc);
|
|
|
|
td->val= NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* in this case we can do target-less IK grabbing */
|
|
|
|
if(t->mode==TFM_TRANSLATION) {
|
|
|
|
bKinematicConstraint *data= has_targetless_ik(pchan);
|
|
|
|
if(data) {
|
|
|
|
if(data->flag & CONSTRAINT_IK_TIP) {
|
|
|
|
VECCOPY(data->grabtarget, pchan->pose_tail);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
VECCOPY(data->grabtarget, pchan->pose_head);
|
|
|
|
}
|
|
|
|
td->loc = data->grabtarget;
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
data->flag |= CONSTRAINT_IK_AUTO;
|
|
|
|
|
|
|
|
/* only object matrix correction */
|
|
|
|
Mat3CpyMat3 (td->mtx, omat);
|
|
|
|
Mat3Inv (td->smtx, td->mtx);
|
|
|
|
}
|
|
|
|
}
|
2007-12-05 11:19:36 +00:00
|
|
|
|
|
|
|
/* store reference to first constraint */
|
|
|
|
td->con= pchan->constraints.first;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void bone_children_clear_transflag(ListBase *lb)
|
|
|
|
{
|
|
|
|
Bone *bone= lb->first;
|
|
|
|
|
|
|
|
for(;bone;bone= bone->next) {
|
2007-12-19 12:12:38 +00:00
|
|
|
if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
|
2007-11-01 12:55:47 +00:00
|
|
|
bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
|
|
|
|
else
|
|
|
|
bone->flag &= ~BONE_TRANSFORM;
|
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
bone_children_clear_transflag(&bone->childbase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sets transform flags in the bones, returns total */
|
|
|
|
static void set_pose_transflags(TransInfo *t, Object *ob)
|
|
|
|
{
|
2005-12-07 12:36:26 +00:00
|
|
|
bArmature *arm= ob->data;
|
2005-10-30 13:50:42 +00:00
|
|
|
bPoseChannel *pchan;
|
|
|
|
Bone *bone;
|
2007-12-08 15:44:47 +00:00
|
|
|
int hastranslation;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
t->total= 0;
|
|
|
|
|
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
bone= pchan->bone;
|
2005-12-07 12:36:26 +00:00
|
|
|
if(bone->layer & arm->layer) {
|
|
|
|
if(bone->flag & BONE_SELECTED)
|
|
|
|
bone->flag |= BONE_TRANSFORM;
|
|
|
|
else
|
|
|
|
bone->flag &= ~BONE_TRANSFORM;
|
2007-11-01 12:55:47 +00:00
|
|
|
|
|
|
|
bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
|
2005-12-07 12:36:26 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure no bone can be transformed when a parent is transformed */
|
|
|
|
/* since pchans are depsgraph sorted, the parents are in beginning of list */
|
2006-08-21 10:27:17 +00:00
|
|
|
if(t->mode!=TFM_BONESIZE) {
|
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
bone= pchan->bone;
|
|
|
|
if(bone->flag & BONE_TRANSFORM)
|
|
|
|
bone_children_clear_transflag(&bone->childbase);
|
|
|
|
}
|
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
/* now count, and check if we have autoIK or have to switch from translate to rotate */
|
2007-12-08 15:44:47 +00:00
|
|
|
hastranslation= 0;
|
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
bone= pchan->bone;
|
|
|
|
if(bone->flag & BONE_TRANSFORM) {
|
2007-12-08 15:44:47 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
t->total++;
|
|
|
|
|
2005-11-01 19:32:54 +00:00
|
|
|
if(t->mode==TFM_TRANSLATION) {
|
2005-11-17 18:01:07 +00:00
|
|
|
if( has_targetless_ik(pchan)==NULL ) {
|
2007-11-01 12:55:47 +00:00
|
|
|
if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
|
2007-12-08 15:44:47 +00:00
|
|
|
if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
|
|
|
|
hastranslation= 1;
|
2007-11-01 12:55:47 +00:00
|
|
|
}
|
2007-12-08 15:44:47 +00:00
|
|
|
else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
|
|
|
|
hastranslation= 1;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
2007-12-08 15:44:47 +00:00
|
|
|
else
|
|
|
|
hastranslation= 1;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-08 15:44:47 +00:00
|
|
|
|
|
|
|
/* if there are no translatable bones, do rotation */
|
|
|
|
if(t->mode==TFM_TRANSLATION && !hastranslation)
|
|
|
|
t->mode= TFM_ROTATION;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
2007-12-15 07:35:16 +00:00
|
|
|
|
|
|
|
/* -------- Auto-IK ---------- */
|
|
|
|
|
|
|
|
/* adjust pose-channel's auto-ik chainlen */
|
|
|
|
static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
|
|
|
|
{
|
|
|
|
bConstraint *con;
|
|
|
|
|
|
|
|
/* don't bother to search if no valid constraints */
|
|
|
|
if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* check if pchan has ik-constraint */
|
|
|
|
for (con= pchan->constraints.first; con; con= con->next) {
|
|
|
|
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
|
|
|
|
bKinematicConstraint *data= con->data;
|
|
|
|
|
|
|
|
/* only accept if a temporary one (for auto-ik) */
|
|
|
|
if (data->flag & CONSTRAINT_IK_TEMP) {
|
|
|
|
/* chainlen is new chainlen, but is limited by maximum chainlen */
|
|
|
|
if ((chainlen==0) || (chainlen > data->max_rootbone))
|
|
|
|
data->rootbone= data->max_rootbone;
|
|
|
|
else
|
|
|
|
data->rootbone= chainlen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* change the chain-length of auto-ik */
|
|
|
|
void transform_autoik_update (TransInfo *t, short mode)
|
|
|
|
{
|
|
|
|
short *chainlen= &G.scene->toolsettings->autoik_chainlen;
|
|
|
|
bPoseChannel *pchan;
|
|
|
|
|
|
|
|
/* mode determines what change to apply to chainlen */
|
|
|
|
if (mode == 1) {
|
|
|
|
/* mode=1 is from WHEELMOUSEDOWN... increases len */
|
|
|
|
(*chainlen)++;
|
|
|
|
}
|
|
|
|
else if (mode == -1) {
|
|
|
|
/* mode==-1 is from WHEELMOUSEUP... decreases len */
|
|
|
|
if (*chainlen > 0) (*chainlen)--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
|
|
|
|
if (ELEM(NULL, t->poseobj, t->poseobj->pose))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* apply to all pose-channels */
|
|
|
|
for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
|
|
|
|
pchan_autoik_adjust(pchan, *chainlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* frees temporal IKs */
|
|
|
|
static void pose_grab_with_ik_clear(Object *ob)
|
|
|
|
{
|
|
|
|
bKinematicConstraint *data;
|
|
|
|
bPoseChannel *pchan;
|
|
|
|
bConstraint *con;
|
|
|
|
|
2007-12-05 11:19:36 +00:00
|
|
|
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
/* clear all temporary lock flags */
|
|
|
|
pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
|
|
|
|
|
|
|
|
/* remove all temporary IK-constraints added */
|
|
|
|
for (con= pchan->constraints.first; con; con= con->next) {
|
|
|
|
if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
|
2005-10-30 13:50:42 +00:00
|
|
|
data= con->data;
|
2007-12-05 11:19:36 +00:00
|
|
|
if (data->flag & CONSTRAINT_IK_TEMP) {
|
2005-10-30 13:50:42 +00:00
|
|
|
BLI_remlink(&pchan->constraints, con);
|
|
|
|
MEM_freeN(con->data);
|
|
|
|
MEM_freeN(con);
|
|
|
|
pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-15 07:35:16 +00:00
|
|
|
/* adds the IK to pchan - returns if added */
|
|
|
|
static short pose_grab_with_ik_add(bPoseChannel *pchan)
|
2005-10-30 13:50:42 +00:00
|
|
|
{
|
|
|
|
bKinematicConstraint *data;
|
|
|
|
bConstraint *con;
|
|
|
|
|
2007-12-15 07:35:16 +00:00
|
|
|
/* Sanity check */
|
|
|
|
if (pchan == NULL)
|
|
|
|
return 0;
|
2006-12-03 18:30:34 +00:00
|
|
|
|
2008-01-06 07:40:37 +00:00
|
|
|
/* Rule: not if there's already an IK on this channel */
|
|
|
|
for (con= pchan->constraints.first; con; con= con->next) {
|
2007-12-15 07:35:16 +00:00
|
|
|
if (con->type==CONSTRAINT_TYPE_KINEMATIC)
|
2005-10-30 13:50:42 +00:00
|
|
|
break;
|
2008-01-06 07:40:37 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
|
2007-12-05 11:19:36 +00:00
|
|
|
if (con) {
|
2005-10-30 13:50:42 +00:00
|
|
|
/* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
|
|
|
|
data= has_targetless_ik(pchan);
|
2007-12-05 11:19:36 +00:00
|
|
|
if (data)
|
2005-10-30 13:50:42 +00:00
|
|
|
data->flag |= CONSTRAINT_IK_AUTO;
|
2007-12-15 07:35:16 +00:00
|
|
|
return 0;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
|
|
|
|
BLI_addtail(&pchan->constraints, con);
|
|
|
|
pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
|
|
|
|
data= con->data;
|
|
|
|
data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
|
|
|
|
VECCOPY(data->grabtarget, pchan->pose_tail);
|
|
|
|
data->rootbone= 1;
|
|
|
|
|
|
|
|
/* we include only a connected chain */
|
2007-12-05 11:19:36 +00:00
|
|
|
while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
|
|
|
|
/* here, we set ik-settings for bone from pchan->protectflag */
|
|
|
|
if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
|
|
|
|
if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
|
|
|
|
if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
|
|
|
|
|
|
|
|
/* now we count this pchan as being included */
|
2005-10-30 13:50:42 +00:00
|
|
|
data->rootbone++;
|
|
|
|
pchan= pchan->parent;
|
|
|
|
}
|
2007-12-15 07:35:16 +00:00
|
|
|
|
|
|
|
/* make a copy of maximum chain-length */
|
|
|
|
data->max_rootbone= data->rootbone;
|
|
|
|
|
|
|
|
return 1;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
2008-01-06 07:40:37 +00:00
|
|
|
/* bone is a candidate to get IK, but we don't do it if it has children connected */
|
2007-12-15 07:35:16 +00:00
|
|
|
static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
|
2005-10-30 13:50:42 +00:00
|
|
|
{
|
|
|
|
Bone *bonec;
|
2007-12-15 07:35:16 +00:00
|
|
|
short wentdeeper=0, added=0;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
/* go deeper if children & children are connected */
|
2007-12-15 07:35:16 +00:00
|
|
|
for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
|
|
|
|
if (bonec->flag & BONE_CONNECTED) {
|
2005-10-30 13:50:42 +00:00
|
|
|
wentdeeper= 1;
|
2007-12-15 07:35:16 +00:00
|
|
|
added+= pose_grab_with_ik_children(pose, bonec);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
2007-12-15 07:35:16 +00:00
|
|
|
if (wentdeeper==0) {
|
2005-10-30 13:50:42 +00:00
|
|
|
bPoseChannel *pchan= get_pose_channel(pose, bone->name);
|
2007-12-15 07:35:16 +00:00
|
|
|
if (pchan)
|
|
|
|
added+= pose_grab_with_ik_add(pchan);
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
2007-12-15 07:35:16 +00:00
|
|
|
|
|
|
|
return added;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* main call which adds temporal IK chains */
|
2007-12-15 07:35:16 +00:00
|
|
|
static short pose_grab_with_ik(Object *ob)
|
2005-10-30 13:50:42 +00:00
|
|
|
{
|
2006-12-03 18:30:34 +00:00
|
|
|
bArmature *arm;
|
2008-01-06 07:40:37 +00:00
|
|
|
bPoseChannel *pchan, *parent;
|
2007-11-08 08:27:21 +00:00
|
|
|
Bone *bonec;
|
2008-01-06 07:40:37 +00:00
|
|
|
short tot_ik= 0;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
2008-01-06 07:40:37 +00:00
|
|
|
if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
|
2007-12-15 07:35:16 +00:00
|
|
|
return 0;
|
2006-12-03 18:30:34 +00:00
|
|
|
|
|
|
|
arm = ob->data;
|
2005-10-30 13:50:42 +00:00
|
|
|
|
2008-01-06 07:40:37 +00:00
|
|
|
/* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
|
2007-12-15 07:35:16 +00:00
|
|
|
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
if (pchan->bone->layer & arm->layer) {
|
|
|
|
if (pchan->bone->flag & BONE_SELECTED) {
|
2008-01-06 07:40:37 +00:00
|
|
|
/* Rule: no IK for solitatry (unconnected) bones */
|
|
|
|
for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
|
|
|
|
if (bonec->flag & BONE_CONNECTED) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* rule: if selected Bone is not a root bone, it gets a temporal IK */
|
|
|
|
if (pchan->parent) {
|
|
|
|
/* only adds if there's no IK yet (and no parent bone was selected) */
|
|
|
|
for (parent= pchan->parent; parent; parent= parent->parent) {
|
|
|
|
if (parent->bone->flag & BONE_SELECTED)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (parent == NULL)
|
|
|
|
tot_ik += pose_grab_with_ik_add(pchan);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* rule: go over the children and add IK to the tips */
|
|
|
|
tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
|
|
|
|
}
|
2005-12-07 12:36:26 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-06 07:40:37 +00:00
|
|
|
return (tot_ik) ? 1 : 0;
|
2005-10-30 13:50:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-23 18:52:31 +00:00
|
|
|
/* only called with pose mode active object now */
|
2005-10-30 13:50:42 +00:00
|
|
|
static void createTransPose(TransInfo *t, Object *ob)
|
2005-04-10 18:33:19 +00:00
|
|
|
{
|
|
|
|
bArmature *arm;
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
bPoseChannel *pchan;
|
2005-04-10 18:33:19 +00:00
|
|
|
TransData *td;
|
|
|
|
TransDataExtension *tdx;
|
2007-12-15 07:35:16 +00:00
|
|
|
short ik_on= 0;
|
2005-04-10 18:33:19 +00:00
|
|
|
int i;
|
|
|
|
|
2005-08-29 18:03:03 +00:00
|
|
|
t->total= 0;
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* check validity of state */
|
2005-07-23 18:52:31 +00:00
|
|
|
arm=get_armature (ob);
|
|
|
|
if (arm==NULL || ob->pose==NULL) return;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
if (arm->flag & ARM_RESTPOS) {
|
|
|
|
if(t->mode!=TFM_BONESIZE) {
|
|
|
|
notice ("Pose edit not possible while Rest Position is enabled");
|
|
|
|
return;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2005-07-23 18:52:31 +00:00
|
|
|
if (!(ob->lay & G.vd->lay)) return;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* do we need to add temporal IK chains? */
|
2007-12-15 07:35:16 +00:00
|
|
|
if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
|
|
|
|
ik_on= pose_grab_with_ik(ob);
|
|
|
|
if (ik_on) t->flag |= T_AUTOIK;
|
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
|
|
|
|
/* set flags and count total (warning, can change transform to rotate) */
|
|
|
|
set_pose_transflags(t, ob);
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
if(t->total==0) return;
|
2005-08-23 18:13:30 +00:00
|
|
|
|
2005-08-16 10:17:02 +00:00
|
|
|
t->flag |= T_POSE;
|
2005-11-01 20:58:37 +00:00
|
|
|
t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
|
2005-08-16 10:17:02 +00:00
|
|
|
|
2005-11-01 20:58:37 +00:00
|
|
|
/* make sure the lock is set OK, unlock can be accidentally saved? */
|
|
|
|
ob->pose->flag |= POSE_LOCKED;
|
|
|
|
ob->pose->flag &= ~POSE_DO_UNLOCK;
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* init trans data */
|
2005-04-11 15:14:07 +00:00
|
|
|
td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
|
|
|
|
tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
|
2005-04-10 18:33:19 +00:00
|
|
|
for(i=0; i<t->total; i++, td++, tdx++) {
|
|
|
|
td->ext= tdx;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
|
|
|
}
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
|
|
|
|
/* use pose channels to fill trans data */
|
2005-04-10 18:33:19 +00:00
|
|
|
td= t->data;
|
2005-07-23 18:52:31 +00:00
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
2005-10-30 13:50:42 +00:00
|
|
|
if(pchan->bone->flag & BONE_TRANSFORM) {
|
|
|
|
add_pose_transdata(t, pchan, ob, td);
|
|
|
|
td++;
|
|
|
|
}
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
if(td != (t->data+t->total)) printf("Bone selection count error\n");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2007-12-15 07:35:16 +00:00
|
|
|
/* initialise initial auto=ik chainlen's? */
|
|
|
|
if (ik_on) transform_autoik_update(t, 0);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* armature ************** */
|
|
|
|
|
|
|
|
static void createTransArmatureVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
EditBone *ebo;
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
bArmature *arm= G.obedit->data;
|
2005-04-10 18:33:19 +00:00
|
|
|
TransData *td;
|
2005-07-16 19:07:02 +00:00
|
|
|
float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
t->total = 0;
|
2005-07-16 19:07:02 +00:00
|
|
|
for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
|
2005-12-07 12:36:26 +00:00
|
|
|
if(ebo->layer & arm->layer) {
|
|
|
|
if (t->mode==TFM_BONESIZE) {
|
|
|
|
if (ebo->flag & BONE_SELECTED)
|
|
|
|
t->total++;
|
|
|
|
}
|
2006-12-03 19:54:27 +00:00
|
|
|
else if (t->mode==TFM_BONE_ROLL) {
|
|
|
|
if (ebo->flag & BONE_SELECTED)
|
|
|
|
t->total++;
|
|
|
|
}
|
2005-12-07 12:36:26 +00:00
|
|
|
else {
|
|
|
|
if (ebo->flag & BONE_TIPSEL)
|
|
|
|
t->total++;
|
|
|
|
if (ebo->flag & BONE_ROOTSEL)
|
|
|
|
t->total++;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!t->total) return;
|
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
2005-10-29 20:08:25 +00:00
|
|
|
td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
|
2005-08-20 09:55:11 +00:00
|
|
|
ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
if(ebo->layer & arm->layer) {
|
|
|
|
if (t->mode==TFM_BONE_ENVELOPE) {
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
if (ebo->flag & BONE_ROOTSEL){
|
|
|
|
td->val= &ebo->rad_head;
|
|
|
|
td->ival= *td->val;
|
|
|
|
|
|
|
|
VECCOPY (td->center, ebo->head);
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td->loc = NULL;
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
|
|
|
|
td++;
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
}
|
2005-12-07 12:36:26 +00:00
|
|
|
if (ebo->flag & BONE_TIPSEL){
|
|
|
|
td->val= &ebo->rad_tail;
|
|
|
|
td->ival= *td->val;
|
|
|
|
VECCOPY (td->center, ebo->tail);
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td->loc = NULL;
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
|
|
|
|
td++;
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
}
|
2005-07-16 19:07:02 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
}
|
|
|
|
else if (t->mode==TFM_BONESIZE) {
|
|
|
|
if (ebo->flag & BONE_SELECTED) {
|
|
|
|
if(arm->drawtype==ARM_ENVELOPE) {
|
|
|
|
td->loc= NULL;
|
|
|
|
td->val= &ebo->dist;
|
|
|
|
td->ival= ebo->dist;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// abusive storage of scale in the loc pointer :)
|
|
|
|
td->loc= &ebo->xwidth;
|
|
|
|
VECCOPY (td->iloc, td->loc);
|
|
|
|
td->val= NULL;
|
|
|
|
}
|
|
|
|
VECCOPY (td->center, ebo->head);
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
|
|
|
|
/* use local bone matrix */
|
|
|
|
VecSubf(delta, ebo->tail, ebo->head);
|
|
|
|
vec_roll_to_mat3(delta, ebo->roll, bonemat);
|
|
|
|
Mat3MulMat3(td->mtx, mtx, bonemat);
|
|
|
|
Mat3Inv(td->smtx, td->mtx);
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->axismtx, td->mtx);
|
|
|
|
Mat3Ortho(td->axismtx);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
|
|
|
|
td++;
|
|
|
|
}
|
2005-07-16 19:07:02 +00:00
|
|
|
}
|
2006-12-03 19:54:27 +00:00
|
|
|
else if (t->mode==TFM_BONE_ROLL) {
|
|
|
|
if (ebo->flag & BONE_SELECTED) {
|
|
|
|
td->loc= NULL;
|
|
|
|
td->val= &(ebo->roll);
|
|
|
|
td->ival= ebo->roll;
|
|
|
|
|
|
|
|
VECCOPY (td->center, ebo->head);
|
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
|
|
|
|
td++;
|
|
|
|
}
|
|
|
|
}
|
2005-12-07 12:36:26 +00:00
|
|
|
else {
|
|
|
|
if (ebo->flag & BONE_TIPSEL){
|
|
|
|
VECCOPY (td->iloc, ebo->tail);
|
|
|
|
VECCOPY (td->center, td->iloc);
|
|
|
|
td->loc= ebo->tail;
|
|
|
|
td->flag= TD_SELECTED;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
td++;
|
|
|
|
}
|
|
|
|
if (ebo->flag & BONE_ROOTSEL){
|
|
|
|
VECCOPY (td->iloc, ebo->head);
|
|
|
|
VECCOPY (td->center, td->iloc);
|
|
|
|
td->loc= ebo->head;
|
|
|
|
td->flag= TD_SELECTED;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
2005-07-16 19:07:02 +00:00
|
|
|
|
2005-12-07 12:36:26 +00:00
|
|
|
td++;
|
|
|
|
}
|
2005-07-16 19:07:02 +00:00
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* meta elements ********* */
|
|
|
|
|
|
|
|
static void createTransMBallVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
|
|
|
TransData *td;
|
|
|
|
TransDataExtension *tx;
|
|
|
|
float mtx[3][3], smtx[3][3];
|
|
|
|
int count=0, countsel=0;
|
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
/* count totals */
|
|
|
|
for(ml= editelems.first; ml; ml= ml->next) {
|
|
|
|
if(ml->flag & SELECT) countsel++;
|
|
|
|
if(propmode) count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (countsel==0) return;
|
|
|
|
|
|
|
|
if(propmode) t->total = count;
|
|
|
|
else t->total = countsel;
|
|
|
|
|
2005-10-29 20:08:25 +00:00
|
|
|
td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
|
|
|
|
tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
|
|
|
for(ml= editelems.first; ml; ml= ml->next) {
|
|
|
|
if(propmode || (ml->flag & SELECT)) {
|
|
|
|
td->loc= &ml->x;
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
VECCOPY(td->center, td->loc);
|
|
|
|
|
2005-04-11 19:31:05 +00:00
|
|
|
if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
|
2005-04-10 18:33:19 +00:00
|
|
|
else td->flag= TD_USEQUAT;
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td->ext = tx;
|
|
|
|
td->tdi = NULL;
|
|
|
|
|
2005-04-11 19:31:05 +00:00
|
|
|
/* Radius of MetaElem (mass of MetaElem influence) */
|
|
|
|
if(ml->flag & MB_SCALE_RAD){
|
|
|
|
td->val = &ml->rad;
|
|
|
|
td->ival = ml->rad;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
td->val = &ml->s;
|
|
|
|
td->ival = ml->s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* expx/expy/expz determine "shape" of some MetaElem types */
|
2005-04-10 18:33:19 +00:00
|
|
|
tx->size = &ml->expx;
|
|
|
|
tx->isize[0] = ml->expx;
|
|
|
|
tx->isize[1] = ml->expy;
|
|
|
|
tx->isize[2] = ml->expz;
|
|
|
|
|
2005-04-11 19:31:05 +00:00
|
|
|
/* quat is used for rotation of MetaElem */
|
2005-04-10 18:33:19 +00:00
|
|
|
tx->quat = ml->quat;
|
|
|
|
QUATCOPY(tx->iquat, ml->quat);
|
|
|
|
|
|
|
|
tx->rot = NULL;
|
|
|
|
|
|
|
|
td++;
|
|
|
|
tx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* curve/surface ********* */
|
|
|
|
|
|
|
|
static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
|
|
|
|
TransData *td, *td_near = NULL;
|
|
|
|
for (td = head; td<=tail; td++) {
|
|
|
|
if (td->flag & TD_SELECTED) {
|
|
|
|
td_near = td;
|
|
|
|
td->dist = 0.0f;
|
|
|
|
}
|
|
|
|
else if(td_near) {
|
|
|
|
float dist;
|
|
|
|
dist = VecLenf(td_near->center, td->center);
|
|
|
|
if (dist < (td-1)->dist) {
|
|
|
|
td->dist = (td-1)->dist;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
td->dist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
td->dist = MAXFLOAT;
|
|
|
|
td->flag |= TD_NOTCONNECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
td_near = NULL;
|
|
|
|
for (td = tail; td>=head; td--) {
|
|
|
|
if (td->flag & TD_SELECTED) {
|
|
|
|
td_near = td;
|
|
|
|
td->dist = 0.0f;
|
|
|
|
}
|
|
|
|
else if(td_near) {
|
|
|
|
float dist;
|
|
|
|
dist = VecLenf(td_near->center, td->center);
|
|
|
|
if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
|
|
|
|
td->flag &= ~TD_NOTCONNECTED;
|
|
|
|
if (dist < (td+1)->dist) {
|
|
|
|
td->dist = (td+1)->dist;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
td->dist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void createTransCurveVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
Nurb *nu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
BPoint *bp;
|
|
|
|
float mtx[3][3], smtx[3][3];
|
|
|
|
int a;
|
|
|
|
int count=0, countsel=0;
|
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
/* count total of vertices, check identical as in 2nd loop for making transdata! */
|
|
|
|
for(nu= editNurb.first; nu; nu= nu->next) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
|
|
|
|
if(bezt->hide==0) {
|
2007-10-25 20:30:18 +00:00
|
|
|
if (G.f & G_HIDDENHANDLES) {
|
2007-12-01 23:25:00 +00:00
|
|
|
if(bezt->f2 & SELECT) countsel+=3;
|
2007-10-25 20:30:18 +00:00
|
|
|
if(propmode) count+= 3;
|
|
|
|
} else {
|
2007-12-01 23:25:00 +00:00
|
|
|
if(bezt->f1 & SELECT) countsel++;
|
|
|
|
if(bezt->f2 & SELECT) countsel++;
|
|
|
|
if(bezt->f3 & SELECT) countsel++;
|
2007-10-25 20:30:18 +00:00
|
|
|
if(propmode) count+= 3;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
|
|
|
|
if(bp->hide==0) {
|
|
|
|
if(propmode) count++;
|
2007-12-11 14:19:05 +00:00
|
|
|
if(bp->f1 & SELECT) countsel++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (countsel==0) return;
|
|
|
|
|
|
|
|
if(propmode) t->total = count;
|
|
|
|
else t->total = countsel;
|
2005-10-29 20:08:25 +00:00
|
|
|
t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
|
|
|
td = t->data;
|
|
|
|
for(nu= editNurb.first; nu; nu= nu->next) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
2005-06-11 02:01:26 +00:00
|
|
|
TransData *head, *tail;
|
|
|
|
head = tail = td;
|
2005-04-10 18:33:19 +00:00
|
|
|
for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
|
|
|
|
if(bezt->hide==0) {
|
2007-10-25 20:30:18 +00:00
|
|
|
|
|
|
|
if( propmode ||
|
2007-12-01 23:25:00 +00:00
|
|
|
((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
|
|
|
|
((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
|
2007-10-25 20:30:18 +00:00
|
|
|
) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->iloc, bezt->vec[0]);
|
|
|
|
td->loc= bezt->vec[0];
|
|
|
|
VECCOPY(td->center, bezt->vec[1]);
|
2007-12-03 23:26:45 +00:00
|
|
|
if (G.f & G_HIDDENHANDLES) {
|
|
|
|
if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
|
|
|
|
else td->flag= 0;
|
|
|
|
} else {
|
|
|
|
if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
|
|
|
|
else td->flag= 0;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td++;
|
|
|
|
count++;
|
2005-06-11 02:01:26 +00:00
|
|
|
tail++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2007-10-25 20:30:18 +00:00
|
|
|
|
|
|
|
/* This is the Curve Point, the other two are handles */
|
2007-12-01 23:25:00 +00:00
|
|
|
if(propmode || (bezt->f2 & SELECT)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->iloc, bezt->vec[1]);
|
|
|
|
td->loc= bezt->vec[1];
|
|
|
|
VECCOPY(td->center, td->loc);
|
2007-12-01 23:25:00 +00:00
|
|
|
if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
|
2005-04-10 18:33:19 +00:00
|
|
|
else td->flag= 0;
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
2006-08-13 07:37:51 +00:00
|
|
|
|
2007-10-25 20:30:18 +00:00
|
|
|
if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
|
2006-08-13 07:37:51 +00:00
|
|
|
td->val = &(bezt->radius);
|
|
|
|
td->ival = bezt->radius;
|
2007-10-25 20:30:18 +00:00
|
|
|
} else if (t->mode==TFM_TILT) {
|
2006-08-13 07:37:51 +00:00
|
|
|
td->val = &(bezt->alfa);
|
|
|
|
td->ival = bezt->alfa;
|
2007-10-25 20:30:18 +00:00
|
|
|
} else {
|
|
|
|
td->val = NULL;
|
2006-08-13 07:37:51 +00:00
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td++;
|
|
|
|
count++;
|
2005-06-11 02:01:26 +00:00
|
|
|
tail++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2007-10-25 20:30:18 +00:00
|
|
|
if( propmode ||
|
2007-12-01 23:25:00 +00:00
|
|
|
((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
|
|
|
|
((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
|
2007-10-25 20:30:18 +00:00
|
|
|
) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->iloc, bezt->vec[2]);
|
|
|
|
td->loc= bezt->vec[2];
|
|
|
|
VECCOPY(td->center, bezt->vec[1]);
|
2007-12-03 23:26:45 +00:00
|
|
|
if (G.f & G_HIDDENHANDLES) {
|
|
|
|
if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
|
|
|
|
else td->flag= 0;
|
|
|
|
} else {
|
|
|
|
if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
|
|
|
|
else td->flag= 0;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td++;
|
|
|
|
count++;
|
2005-06-11 02:01:26 +00:00
|
|
|
tail++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
2005-06-11 02:01:26 +00:00
|
|
|
else if (propmode && head != tail) {
|
|
|
|
calc_distanceCurveVerts(head, tail-1);
|
|
|
|
head = tail;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2005-06-11 02:01:26 +00:00
|
|
|
if (propmode && head != tail)
|
2005-07-08 06:55:10 +00:00
|
|
|
calc_distanceCurveVerts(head, tail-1);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
else {
|
2005-06-11 02:01:26 +00:00
|
|
|
TransData *head, *tail;
|
|
|
|
head = tail = td;
|
2005-04-10 18:33:19 +00:00
|
|
|
for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
|
|
|
|
if(bp->hide==0) {
|
2007-12-11 14:19:05 +00:00
|
|
|
if(propmode || (bp->f1 & SELECT)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->iloc, bp->vec);
|
|
|
|
td->loc= bp->vec;
|
|
|
|
VECCOPY(td->center, td->loc);
|
2007-12-11 14:19:05 +00:00
|
|
|
if(bp->f1 & SELECT) td->flag= TD_SELECTED;
|
2005-04-10 18:33:19 +00:00
|
|
|
else td->flag= 0;
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
2006-08-13 07:37:51 +00:00
|
|
|
|
2007-10-25 20:30:18 +00:00
|
|
|
if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
|
2006-08-13 07:37:51 +00:00
|
|
|
td->val = &(bp->radius);
|
|
|
|
td->ival = bp->radius;
|
|
|
|
} else {
|
|
|
|
td->val = &(bp->alfa);
|
|
|
|
td->ival = bp->alfa;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td++;
|
|
|
|
count++;
|
2005-06-11 02:01:26 +00:00
|
|
|
tail++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
2005-06-11 02:01:26 +00:00
|
|
|
else if (propmode && head != tail) {
|
|
|
|
calc_distanceCurveVerts(head, tail-1);
|
|
|
|
head = tail;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2005-06-11 02:01:26 +00:00
|
|
|
if (propmode && head != tail)
|
|
|
|
calc_distanceCurveVerts(head, tail-1);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************* lattice *************** */
|
|
|
|
|
|
|
|
static void createTransLatticeVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
BPoint *bp;
|
|
|
|
float mtx[3][3], smtx[3][3];
|
|
|
|
int a;
|
|
|
|
int count=0, countsel=0;
|
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
bp= editLatt->def;
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
while(a--) {
|
2005-11-21 11:15:46 +00:00
|
|
|
if(bp->hide==0) {
|
2007-12-11 14:19:05 +00:00
|
|
|
if(bp->f1 & SELECT) countsel++;
|
2005-11-21 11:15:46 +00:00
|
|
|
if(propmode) count++;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (countsel==0) return;
|
|
|
|
|
|
|
|
if(propmode) t->total = count;
|
|
|
|
else t->total = countsel;
|
2005-10-29 20:08:25 +00:00
|
|
|
t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
|
|
|
td = t->data;
|
|
|
|
bp= editLatt->def;
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
while(a--) {
|
2007-12-11 14:19:05 +00:00
|
|
|
if(propmode || (bp->f1 & SELECT)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
if(bp->hide==0) {
|
|
|
|
VECCOPY(td->iloc, bp->vec);
|
|
|
|
td->loc= bp->vec;
|
|
|
|
VECCOPY(td->center, td->loc);
|
2007-12-11 14:19:05 +00:00
|
|
|
if(bp->f1 & SELECT) td->flag= TD_SELECTED;
|
2005-04-10 18:33:19 +00:00
|
|
|
else td->flag= 0;
|
|
|
|
Mat3CpyMat3(td->smtx, smtx);
|
|
|
|
Mat3CpyMat3(td->mtx, mtx);
|
|
|
|
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
|
|
|
|
|
|
|
td++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
/* ******************* particle edit **************** */
|
|
|
|
static void createTransParticleVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
TransDataExtension *tx;
|
|
|
|
Base *base = BASACT;
|
|
|
|
Object *ob = OBACT;
|
|
|
|
ParticleSystem *psys = PE_get_current(ob);
|
|
|
|
ParticleSystemModifierData *psmd = NULL;
|
|
|
|
ParticleEditSettings *pset = PE_settings();
|
|
|
|
ParticleData *pa = NULL;
|
|
|
|
ParticleEdit *edit;
|
|
|
|
ParticleEditKey *key;
|
|
|
|
float mat[4][4];
|
|
|
|
int i,k, totpart, transformparticle;
|
|
|
|
int count = 0, hasselected = 0;
|
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
|
|
|
|
|
|
|
|
psmd = psys_get_modifier(ob,psys);
|
|
|
|
|
|
|
|
edit = psys->edit;
|
|
|
|
totpart = psys->totpart;
|
|
|
|
base->flag |= BA_HAS_RECALC_DATA;
|
|
|
|
|
|
|
|
for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
|
|
|
|
pa->flag &= ~PARS_TRANSFORM;
|
|
|
|
transformparticle= 0;
|
|
|
|
|
|
|
|
if((pa->flag & PARS_HIDE)==0) {
|
|
|
|
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
|
|
|
|
if((key->flag&PEK_HIDE)==0) {
|
|
|
|
if(key->flag&PEK_SELECT) {
|
|
|
|
hasselected= 1;
|
|
|
|
transformparticle= 1;
|
|
|
|
}
|
|
|
|
else if(propmode)
|
|
|
|
transformparticle= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(transformparticle) {
|
|
|
|
count += pa->totkey;
|
|
|
|
pa->flag |= PARS_TRANSFORM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (hasselected==0) return;
|
|
|
|
|
|
|
|
t->total = count;
|
|
|
|
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
|
|
|
|
|
|
|
|
if(t->mode == TFM_BAKE_TIME)
|
|
|
|
tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
|
|
|
|
else
|
|
|
|
tx = t->ext = NULL;
|
|
|
|
|
|
|
|
Mat4One(mat);
|
|
|
|
|
|
|
|
Mat4Invert(ob->imat,ob->obmat);
|
|
|
|
|
|
|
|
for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
|
|
|
|
TransData *head, *tail;
|
|
|
|
head = tail = td;
|
|
|
|
|
|
|
|
if(!(pa->flag & PARS_TRANSFORM)) continue;
|
|
|
|
|
|
|
|
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
|
|
|
|
|
|
|
|
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
|
|
|
|
VECCOPY(key->world_co, key->co);
|
|
|
|
Mat4MulVecfl(mat, key->world_co);
|
|
|
|
td->loc = key->world_co;
|
|
|
|
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
VECCOPY(td->center, td->loc);
|
|
|
|
|
|
|
|
if(key->flag & PEK_SELECT)
|
|
|
|
td->flag |= TD_SELECTED;
|
|
|
|
else if(!propmode)
|
|
|
|
td->flag |= TD_SKIP;
|
|
|
|
|
|
|
|
Mat3One(td->mtx);
|
|
|
|
Mat3One(td->smtx);
|
|
|
|
|
|
|
|
/* don't allow moving roots */
|
|
|
|
if(k==0 && pset->flag & PE_LOCK_FIRST)
|
|
|
|
td->protectflag |= OB_LOCK_LOC;
|
|
|
|
|
2007-12-18 16:55:09 +00:00
|
|
|
td->ob = ob;
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
td->ext = tx;
|
|
|
|
td->tdi = NULL;
|
|
|
|
if(t->mode == TFM_BAKE_TIME) {
|
|
|
|
td->val = key->time;
|
|
|
|
td->ival = *(key->time);
|
|
|
|
/* abuse size and quat for min/max values */
|
|
|
|
td->flag |= TD_NO_EXT;
|
|
|
|
if(k==0) tx->size = 0;
|
|
|
|
else tx->size = (key - 1)->time;
|
|
|
|
|
|
|
|
if(k == pa->totkey - 1) tx->quat = 0;
|
|
|
|
else tx->quat = (key + 1)->time;
|
|
|
|
}
|
|
|
|
|
|
|
|
td++;
|
|
|
|
if(tx)
|
|
|
|
tx++;
|
|
|
|
tail++;
|
|
|
|
}
|
|
|
|
if (propmode && head != tail)
|
|
|
|
calc_distanceCurveVerts(head, tail - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void flushTransParticles(TransInfo *t)
|
|
|
|
{
|
|
|
|
Object *ob = OBACT;
|
|
|
|
ParticleSystem *psys = PE_get_current(ob);
|
|
|
|
ParticleSystemModifierData *psmd;
|
|
|
|
ParticleData *pa;
|
|
|
|
ParticleEditKey *key;
|
|
|
|
TransData *td;
|
|
|
|
float mat[4][4], imat[4][4], co[3];
|
|
|
|
int i, k, propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
|
|
|
psmd = psys_get_modifier(ob, psys);
|
|
|
|
|
|
|
|
/* we do transform in world space, so flush world space position
|
|
|
|
* back to particle local space */
|
|
|
|
td= t->data;
|
|
|
|
for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
|
|
|
|
if(!(pa->flag & PARS_TRANSFORM)) continue;
|
|
|
|
|
|
|
|
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
|
|
|
|
Mat4Invert(imat,mat);
|
|
|
|
|
|
|
|
for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
|
|
|
|
VECCOPY(co, key->world_co);
|
|
|
|
Mat4MulVecfl(imat, co);
|
|
|
|
|
|
|
|
/* optimization for proportional edit */
|
|
|
|
if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
|
|
|
|
VECCOPY(key->co, co);
|
|
|
|
pa->flag |= PARS_EDIT_RECALC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PE_update_object(OBACT, 1);
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* ********************* mesh ****************** */
|
|
|
|
|
|
|
|
/* proportional distance based on connectivity */
|
2006-01-03 17:22:42 +00:00
|
|
|
#define E_VEC(a) (vectors + (3 * (a)->tmp.l))
|
|
|
|
#define E_NEAR(a) (nears[((a)->tmp.l)])
|
2006-11-26 23:54:35 +00:00
|
|
|
#define THRESHOLD 0.0001f
|
2005-04-10 18:33:19 +00:00
|
|
|
static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
|
|
|
|
{
|
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditVert *eve;
|
|
|
|
EditEdge *eed;
|
|
|
|
int i= 0, done= 1;
|
|
|
|
|
|
|
|
/* f2 flag is used for 'selection' */
|
2006-01-03 17:22:42 +00:00
|
|
|
/* tmp.l is offset on scratch array */
|
2005-04-10 18:33:19 +00:00
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
if(eve->h==0) {
|
2006-01-03 17:22:42 +00:00
|
|
|
eve->tmp.l = i++;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
if(eve->f & SELECT) {
|
|
|
|
eve->f2= 2;
|
|
|
|
E_NEAR(eve) = eve;
|
|
|
|
E_VEC(eve)[0] = 0.0f;
|
|
|
|
E_VEC(eve)[1] = 0.0f;
|
|
|
|
E_VEC(eve)[2] = 0.0f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eve->f2 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Floodfill routine */
|
|
|
|
/*
|
|
|
|
At worst this is n*n of complexity where n is number of edges
|
|
|
|
Best case would be n if the list is ordered perfectly.
|
|
|
|
Estimate is n log n in average (so not too bad)
|
|
|
|
*/
|
|
|
|
while(done) {
|
|
|
|
done= 0;
|
|
|
|
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
|
|
if(eed->h==0) {
|
|
|
|
EditVert *v1= eed->v1, *v2= eed->v2;
|
|
|
|
float *vec2 = E_VEC(v2);
|
|
|
|
float *vec1 = E_VEC(v1);
|
|
|
|
|
|
|
|
if (v1->f2 + v2->f2 == 4)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (v1->f2) {
|
|
|
|
if (v2->f2) {
|
|
|
|
float nvec[3];
|
|
|
|
float len1 = VecLength(vec1);
|
|
|
|
float len2 = VecLength(vec2);
|
|
|
|
float lenn;
|
|
|
|
/* for v2 if not selected */
|
|
|
|
if (v2->f2 != 2) {
|
|
|
|
VecSubf(nvec, v2->co, E_NEAR(v1)->co);
|
|
|
|
lenn = VecLength(nvec);
|
2006-11-26 23:54:35 +00:00
|
|
|
/* 1 < n < 2 */
|
|
|
|
if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec2, nvec);
|
|
|
|
E_NEAR(v2) = E_NEAR(v1);
|
|
|
|
done = 1;
|
|
|
|
}
|
2006-11-26 23:54:35 +00:00
|
|
|
/* n < 1 < 2 */
|
|
|
|
else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec2, vec1);
|
|
|
|
E_NEAR(v2) = E_NEAR(v1);
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* for v1 if not selected */
|
|
|
|
if (v1->f2 != 2) {
|
|
|
|
VecSubf(nvec, v1->co, E_NEAR(v2)->co);
|
|
|
|
lenn = VecLength(nvec);
|
2006-11-26 23:54:35 +00:00
|
|
|
/* 2 < n < 1 */
|
|
|
|
if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec1, nvec);
|
|
|
|
E_NEAR(v1) = E_NEAR(v2);
|
|
|
|
done = 1;
|
|
|
|
}
|
2006-11-26 23:54:35 +00:00
|
|
|
/* n < 2 < 1 */
|
|
|
|
else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec1, vec2);
|
|
|
|
E_NEAR(v1) = E_NEAR(v2);
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
v2->f2 = 1;
|
|
|
|
VecSubf(vec2, v2->co, E_NEAR(v1)->co);
|
2006-11-26 23:54:35 +00:00
|
|
|
/* 2 < 1 */
|
|
|
|
if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec2, vec1);
|
|
|
|
}
|
|
|
|
E_NEAR(v2) = E_NEAR(v1);
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (v2->f2) {
|
|
|
|
v1->f2 = 1;
|
|
|
|
VecSubf(vec1, v1->co, E_NEAR(v2)->co);
|
2006-11-26 23:54:35 +00:00
|
|
|
/* 2 < 1 */
|
|
|
|
if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(vec1, vec2);
|
|
|
|
}
|
|
|
|
E_NEAR(v1) = E_NEAR(v2);
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-08 11:07:49 +00:00
|
|
|
/* loop-in-a-loop I know, but we need it! (ton) */
|
|
|
|
static void get_face_center(float *cent, EditVert *eve)
|
|
|
|
{
|
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditFace *efa;
|
|
|
|
|
|
|
|
for(efa= em->faces.first; efa; efa= efa->next)
|
|
|
|
if(efa->f & SELECT)
|
|
|
|
if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
|
|
|
|
break;
|
|
|
|
if(efa) {
|
|
|
|
VECCOPY(cent, efa->cent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
//way to overwrite what data is edited with transform
|
|
|
|
//static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
|
2005-04-10 18:33:19 +00:00
|
|
|
static void VertsToTransData(TransData *td, EditVert *eve)
|
|
|
|
{
|
|
|
|
td->flag = 0;
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
//if(key)
|
|
|
|
// td->loc = key->co;
|
|
|
|
//else
|
2005-04-10 18:33:19 +00:00
|
|
|
td->loc = eve->co;
|
2006-03-08 11:07:49 +00:00
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->center, td->loc);
|
2006-03-08 11:07:49 +00:00
|
|
|
if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
|
|
|
|
get_face_center(td->center, eve);
|
2005-04-10 18:33:19 +00:00
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
|
|
|
|
// Setting normals
|
|
|
|
VECCOPY(td->axismtx[2], eve->no);
|
|
|
|
td->axismtx[0][0] =
|
|
|
|
td->axismtx[0][1] =
|
|
|
|
td->axismtx[0][2] =
|
|
|
|
td->axismtx[1][0] =
|
|
|
|
td->axismtx[1][1] =
|
|
|
|
td->axismtx[1][2] = 0.0f;
|
|
|
|
|
|
|
|
td->ext = NULL;
|
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
2005-12-01 19:04:57 +00:00
|
|
|
td->tdmir= NULL;
|
2008-02-23 22:46:55 +00:00
|
|
|
if (BIF_GetTransInfo()->mode == TFM_BWEIGHT) {
|
|
|
|
td->val = &(eve->bweight);
|
|
|
|
td->ival = eve->bweight;
|
|
|
|
}
|
2006-08-20 15:22:56 +00:00
|
|
|
|
|
|
|
#ifdef WITH_VERSE
|
|
|
|
if(eve->vvert) {
|
|
|
|
td->verse = (void*)eve->vvert;
|
|
|
|
td->flag |= TD_VERSE_VERT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
td->flag &= ~TD_VERSE_VERT;
|
|
|
|
#endif
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
|
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
|
|
|
{
|
|
|
|
float *vec = userData;
|
|
|
|
|
|
|
|
vec+= 3*index;
|
|
|
|
VECCOPY(vec, co);
|
|
|
|
}
|
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
static int modifiers_disable_subsurf_temporary(Object *ob)
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
{
|
2006-01-04 15:37:48 +00:00
|
|
|
ModifierData *md;
|
2007-07-28 21:04:30 +00:00
|
|
|
int disabled = 0;
|
2006-01-04 15:37:48 +00:00
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
for(md=ob->modifiers.first; md; md=md->next)
|
|
|
|
if(md->type==eModifierType_Subsurf)
|
|
|
|
if(md->mode & eModifierMode_OnCage) {
|
|
|
|
md->mode ^= eModifierMode_DisableTemporary;
|
|
|
|
disabled= 1;
|
|
|
|
}
|
2006-01-04 15:37:48 +00:00
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
return disabled;
|
2006-01-04 15:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* disable subsurf temporal, get mapped cos, and enable it */
|
|
|
|
static float *get_crazy_mapped_editverts(void)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm;
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
float *vertexcos;
|
2007-07-28 21:04:30 +00:00
|
|
|
|
|
|
|
/* disable subsurf temporal, get mapped cos, and enable it */
|
|
|
|
if(modifiers_disable_subsurf_temporary(G.obedit)) {
|
|
|
|
/* need to make new derivemesh */
|
2006-12-05 17:42:03 +00:00
|
|
|
makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
|
2006-01-04 15:37:48 +00:00
|
|
|
}
|
2007-07-28 21:04:30 +00:00
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
/* now get the cage */
|
2006-12-05 17:42:03 +00:00
|
|
|
dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
2006-01-04 15:37:48 +00:00
|
|
|
|
|
|
|
vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
dm->release(dm);
|
2006-01-04 15:37:48 +00:00
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
/* set back the flag, no new cage needs to be built, transform does it */
|
|
|
|
modifiers_disable_subsurf_temporary(G.obedit);
|
2006-01-04 15:37:48 +00:00
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
return vertexcos;
|
|
|
|
}
|
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
#define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
|
|
|
|
static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
{
|
2006-01-04 15:37:48 +00:00
|
|
|
float vecu[3], vecv[3];
|
|
|
|
float q1[4], q2[4];
|
|
|
|
|
|
|
|
TAN_MAKE_VEC(vecu, v1, v2);
|
|
|
|
TAN_MAKE_VEC(vecv, v1, v3);
|
|
|
|
triatoquat(v1, vecu, vecv, q1);
|
|
|
|
|
|
|
|
TAN_MAKE_VEC(vecu, def1, def2);
|
|
|
|
TAN_MAKE_VEC(vecv, def1, def3);
|
|
|
|
triatoquat(def1, vecu, vecv, q2);
|
|
|
|
|
|
|
|
QuatSub(quat, q2, q1);
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
}
|
2006-01-04 15:37:48 +00:00
|
|
|
#undef TAN_MAKE_VEC
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
{
|
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditVert *eve, *prev;
|
|
|
|
EditFace *efa;
|
2007-07-28 21:04:30 +00:00
|
|
|
float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
|
2007-04-29 10:49:02 +00:00
|
|
|
long index= 0;
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
/* two abused locations in vertices */
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
for(eve= em->verts.first; eve; eve= eve->next, index++) {
|
2007-09-27 17:45:53 +00:00
|
|
|
eve->tmp.p = NULL;
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
eve->prev= (EditVert *)index;
|
|
|
|
}
|
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
for(efa= em->faces.first; efa; efa= efa->next) {
|
|
|
|
|
2006-01-04 15:37:48 +00:00
|
|
|
/* retrieve mapped coordinates */
|
2007-07-28 21:04:30 +00:00
|
|
|
v1= mappedcos + 3*(long)(efa->v1->prev);
|
|
|
|
v2= mappedcos + 3*(long)(efa->v2->prev);
|
|
|
|
v3= mappedcos + 3*(long)(efa->v3->prev);
|
|
|
|
|
|
|
|
co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co;
|
|
|
|
co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co;
|
|
|
|
co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co;
|
|
|
|
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v2->tmp.p==NULL && efa->v2->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v2->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(efa->v4) {
|
2007-07-28 21:04:30 +00:00
|
|
|
v4= mappedcos + 3*(long)(efa->v4->prev);
|
|
|
|
co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co;
|
|
|
|
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v1->tmp.p==NULL && efa->v1->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v1->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v3->tmp.p==NULL && efa->v3->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v3->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v4->tmp.p==NULL && efa->v4->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v4->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v1->tmp.p==NULL && efa->v1->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v1->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
2007-09-27 17:45:53 +00:00
|
|
|
if(efa->v3->tmp.p==NULL && efa->v3->f1) {
|
2007-07-28 21:04:30 +00:00
|
|
|
set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
|
2007-09-27 17:45:53 +00:00
|
|
|
efa->v3->tmp.p= (void*)quats;
|
2006-01-04 15:37:48 +00:00
|
|
|
quats+= 4;
|
|
|
|
}
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore abused prev pointer */
|
|
|
|
for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
|
|
|
|
eve->prev= prev;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-02-23 22:46:55 +00:00
|
|
|
void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
|
|
|
|
BME_Vert *v;
|
|
|
|
BME_TransData *vtd;
|
|
|
|
TransData *tob;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
|
|
|
|
|
|
|
|
for (i=0,v=bm->verts.first;v;v=v->next) {
|
2008-02-25 04:38:48 +00:00
|
|
|
if ( (vtd = BME_get_transdata(td,v)) ) {
|
2008-02-23 22:46:55 +00:00
|
|
|
tob->loc = vtd->loc;
|
|
|
|
tob->val = &vtd->factor;
|
|
|
|
VECCOPY(tob->iloc,vtd->co);
|
|
|
|
VECCOPY(tob->center,vtd->org);
|
|
|
|
VECCOPY(tob->axismtx[0],vtd->vec);
|
|
|
|
tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
|
|
|
|
tob++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* since td is a memarena, it can hold more transdata than actual elements
|
|
|
|
* (i.e. we can't depend on td->len to determine the number of actual elements) */
|
|
|
|
t->total = i;
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
static void createTransEditVerts(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *tob = NULL;
|
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditVert *eve;
|
|
|
|
EditVert **nears = NULL;
|
2008-01-20 22:43:48 +00:00
|
|
|
EditVert *eve_act = NULL;
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
|
2007-07-28 21:04:30 +00:00
|
|
|
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
|
|
|
|
int count=0, countsel=0, a, totleft;
|
2005-04-10 18:33:19 +00:00
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
2007-11-26 01:52:48 +00:00
|
|
|
int mirror = 0;
|
|
|
|
|
|
|
|
if ((t->context & CTX_NO_MIRROR) == 0 || (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
|
|
|
|
{
|
|
|
|
mirror = 1;
|
|
|
|
}
|
2005-12-01 19:04:57 +00:00
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
// transform now requires awareness for select mode, so we tag the f1 flags in verts
|
|
|
|
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
if(eve->h==0 && (eve->f & SELECT))
|
|
|
|
eve->f1= SELECT;
|
|
|
|
else
|
|
|
|
eve->f1= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
|
|
|
|
EditEdge *eed;
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
|
|
if(eed->h==0 && (eed->f & SELECT))
|
|
|
|
eed->v1->f1= eed->v2->f1= SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
EditFace *efa;
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
|
|
|
|
for(efa= em->faces.first; efa; efa= efa->next) {
|
|
|
|
if(efa->h==0 && (efa->f & SELECT)) {
|
|
|
|
efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
|
|
|
|
if(efa->v4) efa->v4->f1= SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now we can count */
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
if(eve->h==0) {
|
|
|
|
if(eve->f1) countsel++;
|
|
|
|
if(propmode) count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (countsel==0) return;
|
|
|
|
|
2008-01-20 22:43:48 +00:00
|
|
|
/* check active */
|
|
|
|
if (G.editMesh->selected.last) {
|
|
|
|
EditSelection *ese = G.editMesh->selected.last;
|
|
|
|
if ( ese->type == EDITVERT ) {
|
|
|
|
eve_act = (EditVert *)ese->data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
if(propmode) {
|
|
|
|
t->total = count;
|
|
|
|
|
|
|
|
/* allocating scratch arrays */
|
2005-04-17 17:43:07 +00:00
|
|
|
vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
|
|
|
|
nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
else t->total = countsel;
|
2005-10-29 20:08:25 +00:00
|
|
|
tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
Mat3CpyMat4(mtx, G.obedit->obmat);
|
|
|
|
Mat3Inv(smtx, mtx);
|
|
|
|
|
|
|
|
if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
|
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
/* detect CrazySpace [tm] */
|
2005-10-26 10:49:19 +00:00
|
|
|
if(propmode==0) {
|
|
|
|
if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
|
|
|
|
if(modifiers_isDeformed(G.obedit)) {
|
2007-07-28 21:04:30 +00:00
|
|
|
/* check if we can use deform matrices for modifier from the
|
|
|
|
start up to stack, they are more accurate than quats */
|
|
|
|
totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
|
|
|
|
|
|
|
|
/* if we still have more modifiers, also do crazyspace
|
|
|
|
correction with quats, relative to the coordinates after
|
|
|
|
the modifiers that support deform matrices (defcos) */
|
|
|
|
if(totleft > 0) {
|
|
|
|
mappedcos= get_crazy_mapped_editverts();
|
|
|
|
quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
|
|
|
|
set_crazyspace_quats((float*)defcos, mappedcos, quats);
|
|
|
|
if(mappedcos)
|
|
|
|
MEM_freeN(mappedcos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(defcos)
|
|
|
|
MEM_freeN(defcos);
|
2005-10-26 10:49:19 +00:00
|
|
|
}
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-01 19:04:57 +00:00
|
|
|
/* find out which half we do */
|
|
|
|
if(mirror) {
|
|
|
|
for (eve=em->verts.first; eve; eve=eve->next) {
|
|
|
|
if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
|
|
|
|
if(eve->co[0]<0.0f)
|
|
|
|
mirror = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
|
2005-04-10 18:33:19 +00:00
|
|
|
if(eve->h==0) {
|
|
|
|
if(propmode || eve->f1) {
|
|
|
|
VertsToTransData(tob, eve);
|
2008-01-20 22:43:48 +00:00
|
|
|
|
|
|
|
/* selected */
|
2005-04-10 18:33:19 +00:00
|
|
|
if(eve->f1) tob->flag |= TD_SELECTED;
|
2008-01-20 22:43:48 +00:00
|
|
|
|
|
|
|
/* active */
|
|
|
|
if(eve == eve_act) tob->flag |= TD_ACTIVE;
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
if(propmode) {
|
|
|
|
if (eve->f2) {
|
|
|
|
float vec[3];
|
|
|
|
VECCOPY(vec, E_VEC(eve));
|
|
|
|
Mat3MulVecfl(mtx, vec);
|
|
|
|
tob->dist= VecLength(vec);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tob->flag |= TD_NOTCONNECTED;
|
|
|
|
tob->dist = MAXFLOAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
/* CrazySpace */
|
2007-09-27 17:45:53 +00:00
|
|
|
if(defmats || (quats && eve->tmp.p)) {
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
float mat[3][3], imat[3][3], qmat[3][3];
|
|
|
|
|
2007-07-28 21:04:30 +00:00
|
|
|
/* use both or either quat and defmat correction */
|
|
|
|
if(quats && eve->tmp.f) {
|
2007-09-27 17:45:53 +00:00
|
|
|
QuatToMat3(eve->tmp.p, qmat);
|
2007-07-28 21:04:30 +00:00
|
|
|
|
|
|
|
if(defmats)
|
|
|
|
Mat3MulSerie(mat, mtx, qmat, defmats[a],
|
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
else
|
|
|
|
Mat3MulMat3(mat, mtx, qmat);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Mat3MulMat3(mat, mtx, defmats[a]);
|
|
|
|
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
Mat3Inv(imat, mat);
|
|
|
|
|
|
|
|
Mat3CpyMat3(tob->smtx, imat);
|
|
|
|
Mat3CpyMat3(tob->mtx, mat);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Mat3CpyMat3(tob->smtx, smtx);
|
|
|
|
Mat3CpyMat3(tob->mtx, mtx);
|
|
|
|
}
|
2005-12-01 19:04:57 +00:00
|
|
|
|
|
|
|
/* Mirror? */
|
|
|
|
if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
|
|
|
|
EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
|
|
|
|
if(vmir!=eve) tob->tdmir= vmir;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
tob++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (propmode) {
|
2005-04-17 17:43:07 +00:00
|
|
|
MEM_freeN(vectors);
|
|
|
|
MEM_freeN(nears);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
New: CrazySpace [tm] correction
When Modifiers are used in Edit Mode to show the deformed result for
editing, all actual coordinates Blender works with are still the ones from
the original Cage. You can notice that with the Transform Widget or
helper lines while transforming.
Even worse, the actual transformations still happened on the original Cage
as well, making it very hard to edit. That caused the feature to be named
"CrazySpace" (baptized by Andy, afaik?).
This commit calculates the deformation transformation per vertex, and
inverse corrects it, so it's more intuitive editing this way.
Unfortunately all the deformation features of Blender don't use matrices
for defining deform, so the existing code cannot be re-used to retrieve
the correct deformation matrix per vertex. The solution I found is based
on calculating per face the transformation based on its first 3 vertices,
and store this transformation averaged in the face's vertices.
The solution can also only work on entire faces, because the full deform
can only be retrieved using 3 vertices. (using 2 vertices will miss edge-
aligned rotation, using 1 vertex can only retrieve translation).
By deriving the deformations per face, small errors will still happen,
especially on very low-poly Meshes with extreme deformations.
The only alternative I know now, is providing each vertex in
a mesh with 2 extreme small tangent vectors, which get deformed using the
existing code as well. That will mess up the existing deformation code too
much though, this solution has the benefit it works with each deform we can
up with later too.
Last note about CrazySpace: it can only be used to tweak Meshes. Do not
even try to add vertices, extrude, or duplicate. Probably we should disable
this... but preventing user errors isn't always power-user-friendly, eh. :)
2005-10-26 09:56:52 +00:00
|
|
|
/* crazy space free */
|
|
|
|
if(quats)
|
|
|
|
MEM_freeN(quats);
|
2007-07-28 21:04:30 +00:00
|
|
|
if(defmats)
|
|
|
|
MEM_freeN(defmats);
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
2005-08-23 18:13:30 +00:00
|
|
|
/* ********************* UV ****************** */
|
|
|
|
|
|
|
|
static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
|
|
|
|
{
|
|
|
|
float aspx, aspy;
|
|
|
|
|
|
|
|
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
|
|
|
|
|
|
|
/* uv coords are scaled by aspects. this is needed for rotations and
|
|
|
|
proportional editing to be consistent with the stretchted uv coords
|
|
|
|
that are displayed. this also means that for display and numinput,
|
|
|
|
and when the the uv coords are flushed, these are converted each time */
|
|
|
|
td2d->loc[0] = uv[0]*aspx;
|
|
|
|
td2d->loc[1] = uv[1]*aspy;
|
|
|
|
td2d->loc[2] = 0.0f;
|
|
|
|
td2d->loc2d = uv;
|
|
|
|
|
|
|
|
td->flag = 0;
|
|
|
|
td->loc = td2d->loc;
|
|
|
|
VECCOPY(td->center, td->loc);
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
|
|
|
|
memset(td->axismtx, 0, sizeof(td->axismtx));
|
|
|
|
td->axismtx[2][2] = 1.0f;
|
|
|
|
|
|
|
|
td->ext= NULL; td->tdi= NULL; td->val= NULL;
|
|
|
|
|
|
|
|
if(selected) {
|
|
|
|
td->flag |= TD_SELECTED;
|
|
|
|
td->dist= 0.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
td->dist= MAXFLOAT;
|
|
|
|
|
|
|
|
Mat3One(td->mtx);
|
|
|
|
Mat3One(td->smtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void createTransUVs(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
TransData2D *td2d = NULL;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MTFace *tf;
|
2007-09-10 12:26:36 +00:00
|
|
|
int count=0, countsel=0;
|
2005-08-23 18:13:30 +00:00
|
|
|
int propmode = t->flag & T_PROP_EDIT;
|
|
|
|
|
2007-09-10 12:26:36 +00:00
|
|
|
EditMesh *em = G.editMesh;
|
|
|
|
EditFace *efa;
|
|
|
|
|
2005-08-23 18:13:30 +00:00
|
|
|
if(is_uv_tface_editing_allowed()==0) return;
|
|
|
|
|
|
|
|
/* count */
|
2007-09-10 12:26:36 +00:00
|
|
|
for (efa= em->faces.first; efa; efa= efa->next) {
|
2007-09-19 10:54:49 +00:00
|
|
|
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
|
2007-11-25 13:43:14 +00:00
|
|
|
if (simaFaceDraw_Check(efa, tf)) {
|
|
|
|
if (simaUVSel_Check(efa, tf, 0)) countsel++;
|
|
|
|
if (simaUVSel_Check(efa, tf, 1)) countsel++;
|
|
|
|
if (simaUVSel_Check(efa, tf, 2)) countsel++;
|
|
|
|
if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
|
2005-08-23 18:13:30 +00:00
|
|
|
if(propmode)
|
2007-09-10 12:26:36 +00:00
|
|
|
count += (efa->v4)? 4: 3;
|
2005-08-23 18:13:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: in prop mode we need at least 1 selected */
|
|
|
|
if (countsel==0) return;
|
|
|
|
|
|
|
|
t->total= (propmode)? count: countsel;
|
2005-10-29 20:08:25 +00:00
|
|
|
t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
|
2005-08-23 18:13:30 +00:00
|
|
|
/* for each 2d uv coord a 3d vector is allocated, so that they can be
|
|
|
|
treated just as if they were 3d verts */
|
2007-09-30 11:43:16 +00:00
|
|
|
t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
|
2005-08-23 18:13:30 +00:00
|
|
|
|
|
|
|
if(G.sima->flag & SI_CLIP_UV)
|
|
|
|
t->flag |= T_CLIP_UV;
|
|
|
|
|
|
|
|
td= t->data;
|
|
|
|
td2d= t->data2d;
|
2007-09-10 12:26:36 +00:00
|
|
|
for (efa= em->faces.first; efa; efa= efa->next) {
|
2007-09-19 10:54:49 +00:00
|
|
|
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
|
2007-11-25 13:43:14 +00:00
|
|
|
if (simaFaceDraw_Check(efa, tf)) {
|
|
|
|
if(propmode || simaUVSel_Check(efa, tf, 0))
|
|
|
|
UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
|
|
|
|
if(propmode || simaUVSel_Check(efa, tf, 1))
|
|
|
|
UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
|
|
|
|
if(propmode || simaUVSel_Check(efa, tf, 2))
|
|
|
|
UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
|
|
|
|
|
|
|
|
if(efa->v4 && (propmode || simaUVSel_Check(efa, tf, 3)))
|
|
|
|
UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
|
2005-08-23 18:13:30 +00:00
|
|
|
}
|
|
|
|
}
|
2005-12-03 23:22:31 +00:00
|
|
|
|
2006-02-05 14:12:45 +00:00
|
|
|
if (G.sima->flag & SI_LIVE_UNWRAP)
|
2005-12-03 23:22:31 +00:00
|
|
|
unwrap_lscm_live_begin();
|
2005-08-23 18:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void flushTransUVs(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData2D *td;
|
|
|
|
int a, width, height;
|
|
|
|
Object *ob= OBACT;
|
2007-09-10 12:26:36 +00:00
|
|
|
EditMesh *em = G.editMesh;
|
2005-08-23 18:13:30 +00:00
|
|
|
float aspx, aspy, invx, invy;
|
|
|
|
|
|
|
|
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
|
|
|
transform_width_height_tface_uv(&width, &height);
|
|
|
|
invx= 1.0f/aspx;
|
|
|
|
invy= 1.0f/aspy;
|
|
|
|
|
|
|
|
/* flush to 2d vector from internally used 3d vector */
|
|
|
|
for(a=0, td= t->data2d; a<t->total; a++, td++) {
|
|
|
|
td->loc2d[0]= td->loc[0]*invx;
|
|
|
|
td->loc2d[1]= td->loc[1]*invy;
|
|
|
|
|
|
|
|
if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
|
2006-06-24 14:16:36 +00:00
|
|
|
td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
|
|
|
|
td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
|
2005-08-23 18:13:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-22 11:25:39 +00:00
|
|
|
/* always call this, also for cancel (it transforms non-selected vertices...) */
|
|
|
|
if((G.sima->flag & SI_BE_SQUARE))
|
2007-09-10 12:26:36 +00:00
|
|
|
be_square_tface_uv(em);
|
2005-08-23 18:13:30 +00:00
|
|
|
|
|
|
|
/* this is overkill if G.sima->lock is not set, but still needed */
|
|
|
|
object_uvs_changed(ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
int clipUVTransform(TransInfo *t, float *vec, int resize)
|
|
|
|
{
|
|
|
|
TransData *td;
|
|
|
|
int a, clipx=1, clipy=1;
|
|
|
|
float aspx, aspy, min[2], max[2];
|
|
|
|
|
|
|
|
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
|
|
|
min[0]= min[1]= 0.0f;
|
|
|
|
max[0]= aspx; max[1]= aspy;
|
|
|
|
|
|
|
|
for(a=0, td= t->data; a<t->total; a++, td++) {
|
|
|
|
DO_MINMAX2(td->loc, min, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(resize) {
|
|
|
|
if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
|
|
|
|
vec[0] *= t->center[0]/(t->center[0] - min[0]);
|
|
|
|
else if(max[0] > aspx && t->center[0] < aspx)
|
|
|
|
vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
|
|
|
|
else
|
|
|
|
clipx= 0;
|
|
|
|
|
|
|
|
if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
|
|
|
|
vec[1] *= t->center[1]/(t->center[1] - min[1]);
|
|
|
|
else if(max[1] > aspy && t->center[1] < aspy)
|
|
|
|
vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
|
|
|
|
else
|
|
|
|
clipy= 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(min[0] < 0.0f)
|
|
|
|
vec[0] -= min[0];
|
|
|
|
else if(max[0] > aspx)
|
|
|
|
vec[0] -= max[0]-aspx;
|
|
|
|
else
|
|
|
|
clipx= 0;
|
|
|
|
|
|
|
|
if(min[1] < 0.0f)
|
|
|
|
vec[1] -= min[1];
|
|
|
|
else if(max[1] > aspy)
|
|
|
|
vec[1] -= max[1]-aspy;
|
|
|
|
else
|
|
|
|
clipy= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (clipx || clipy);
|
|
|
|
}
|
|
|
|
|
2007-09-30 11:43:16 +00:00
|
|
|
/* ********************* IPO EDITOR ************************* */
|
|
|
|
|
|
|
|
/* for IPO Editor transform - but actual creation of transform structures is not performed here
|
|
|
|
* due to bad globals that would need to be imported specially for this
|
|
|
|
*/
|
|
|
|
static void createTransIpoData(TransInfo *t)
|
|
|
|
{
|
|
|
|
/* in editipo.c due to some globals that are defined in that file... */
|
|
|
|
make_ipo_transdata(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this function is called on recalcData to apply the transforms applied
|
|
|
|
* to the transdata on to the actual keyframe data
|
|
|
|
*/
|
|
|
|
void flushTransIpoData(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData2D *td;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
/* flush to 2d vector from internally used 3d vector */
|
|
|
|
for (a=0, td= t->data2d; a<t->total; a++, td++) {
|
|
|
|
/* we need to unapply the nla-scaling from the time in some situations */
|
|
|
|
if (NLA_IPO_SCALED)
|
|
|
|
td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
|
|
|
|
else
|
|
|
|
td->loc2d[0]= td->loc[0];
|
|
|
|
|
|
|
|
/* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
|
|
|
|
if ((t->data[a].flag & TD_TIMEONLY)==0)
|
|
|
|
td->loc2d[1]= td->loc[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-24 11:29:25 +00:00
|
|
|
/* ********************* ACTION/NLA EDITOR ****************** */
|
|
|
|
|
2008-01-28 11:38:12 +00:00
|
|
|
/* Called by special_aftertrans_update to make sure selected keyframes replace
|
|
|
|
* any other keyframes which may reside on that frame (that is not selected).
|
|
|
|
*/
|
|
|
|
static void posttrans_ipo_clean (Ipo *ipo)
|
|
|
|
{
|
|
|
|
IpoCurve *icu;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
|
|
|
|
for (icu= ipo->curve.first; icu; icu= icu->next) {
|
|
|
|
float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
|
|
|
|
int len, index; /* number of frames in cache, item index */
|
|
|
|
|
|
|
|
/* allocate memory for the cache */
|
|
|
|
// TODO: investigate using GHash for this instead?
|
|
|
|
if (icu->totvert == 0)
|
|
|
|
continue;
|
|
|
|
selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
|
|
|
|
len= 0;
|
|
|
|
index= 0;
|
|
|
|
|
|
|
|
/* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
|
|
|
|
* as there is no guarantee what order the keyframes are exactly, even though
|
|
|
|
* they have been sorted by time.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Loop 1: find selected keyframes */
|
|
|
|
for (i = 0; i < icu->totvert; i++) {
|
|
|
|
BezTriple *bezt= &icu->bezt[i];
|
|
|
|
|
|
|
|
if (BEZSELECTED(bezt)) {
|
|
|
|
selcache[index]= bezt->vec[1][0];
|
|
|
|
index++;
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
|
|
|
|
if (len) {
|
|
|
|
for (i = 0; i < icu->totvert; i++) {
|
|
|
|
BezTriple *bezt= &icu->bezt[i];
|
|
|
|
|
|
|
|
if (BEZSELECTED(bezt) == 0) {
|
|
|
|
/* check beztriple should be removed according to cache */
|
|
|
|
for (index= 0; index < len; index++) {
|
|
|
|
if (IS_EQ(bezt->vec[1][0], selcache[index])) {
|
|
|
|
delete_icu_key(icu, i, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (bezt->vec[1][0] > selcache[index])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
testhandles_ipocurve(icu);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free cache */
|
|
|
|
MEM_freeN(selcache);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Called by special_aftertrans_update to make sure selected keyframes replace
|
|
|
|
* any other keyframes which may reside on that frame (that is not selected).
|
|
|
|
* remake_action_ipos should have already been called
|
|
|
|
*/
|
|
|
|
static void posttrans_action_clean (bAction *act)
|
|
|
|
{
|
|
|
|
ListBase act_data = {NULL, NULL};
|
|
|
|
bActListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
/* filter data */
|
|
|
|
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
|
|
|
|
actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
|
|
|
|
|
|
|
|
/* loop through relevant data, removing keyframes from the ipo-blocks that were attached
|
|
|
|
* - all keyframes are converted in/out of global time
|
|
|
|
*/
|
|
|
|
for (ale= act_data.first; ale; ale= ale->next) {
|
|
|
|
if (NLA_ACTION_SCALED) {
|
|
|
|
actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
|
|
|
|
posttrans_ipo_clean(ale->key_data);
|
|
|
|
actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
posttrans_ipo_clean(ale->key_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free temp data */
|
|
|
|
BLI_freelistN(&act_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------- */
|
|
|
|
|
2007-11-06 11:41:09 +00:00
|
|
|
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
|
|
|
|
static short FrameOnMouseSide(char side, float frame, float cframe)
|
|
|
|
{
|
|
|
|
/* both sides, so it doesn't matter */
|
|
|
|
if (side == 'B') return 1;
|
|
|
|
|
|
|
|
/* only on the named side */
|
|
|
|
if (side == 'R')
|
|
|
|
return (frame >= cframe) ? 1 : 0;
|
|
|
|
else
|
|
|
|
return (frame <= cframe) ? 1 : 0;
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
|
2007-11-06 11:41:09 +00:00
|
|
|
/* fully select selected beztriples, but only include if it's on the right side of cfra */
|
|
|
|
static int count_ipo_keys(Ipo *ipo, char side, float cfra)
|
|
|
|
{
|
|
|
|
IpoCurve *icu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int i, count = 0;
|
|
|
|
|
|
|
|
if (ipo == NULL)
|
|
|
|
return count;
|
|
|
|
|
|
|
|
/* only include points that occur on the right side of cfra */
|
|
|
|
for (icu= ipo->curve.first; icu; icu= icu->next) {
|
|
|
|
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
|
2007-12-01 23:25:00 +00:00
|
|
|
if (bezt->f2 & SELECT) {
|
2007-11-06 11:41:09 +00:00
|
|
|
/* fully select the other two keys */
|
2007-12-01 23:25:00 +00:00
|
|
|
bezt->f1 |= SELECT;
|
|
|
|
bezt->f3 |= SELECT;
|
2007-11-06 11:41:09 +00:00
|
|
|
|
|
|
|
/* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
|
|
|
|
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
|
|
|
|
count += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function assigns the information to transdata */
|
2007-09-24 11:29:25 +00:00
|
|
|
static void TimeToTransData(TransData *td, float *time, Object *ob)
|
|
|
|
{
|
|
|
|
/* memory is calloc'ed, so that should zero everything nicely for us */
|
|
|
|
td->val = time;
|
|
|
|
td->ival = *(time);
|
|
|
|
|
|
|
|
/* store the Object where this keyframe exists as a keyframe of the
|
|
|
|
* active action as td->ob. Usually, this member is only used for constraints
|
|
|
|
* drawing
|
|
|
|
*/
|
|
|
|
td->ob= ob;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function advances the address to which td points to, so it must return
|
|
|
|
* the new address so that the next time new transform data is added, it doesn't
|
2007-11-06 11:41:09 +00:00
|
|
|
* overwrite the existing ones... i.e. td = IpoToTransData(td, ipo, ob, side, cfra);
|
|
|
|
*
|
|
|
|
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
|
|
|
|
* on the named side are used.
|
2007-09-24 11:29:25 +00:00
|
|
|
*/
|
2007-11-06 11:41:09 +00:00
|
|
|
static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob, char side, float cfra)
|
2007-09-24 11:29:25 +00:00
|
|
|
{
|
|
|
|
IpoCurve *icu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ipo == NULL)
|
|
|
|
return td;
|
|
|
|
|
|
|
|
for (icu= ipo->curve.first; icu; icu= icu->next) {
|
|
|
|
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
|
2007-11-06 11:41:09 +00:00
|
|
|
/* only add selected keyframes (for now, proportional edit is not enabled) */
|
2007-09-24 11:29:25 +00:00
|
|
|
if (BEZSELECTED(bezt)) {
|
2007-11-06 11:41:09 +00:00
|
|
|
/* only add if on the right 'side' of the current frame */
|
|
|
|
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
|
|
|
|
/* each control point needs to be added separetely */
|
|
|
|
TimeToTransData(td, bezt->vec[0], ob);
|
|
|
|
td++;
|
|
|
|
|
|
|
|
TimeToTransData(td, bezt->vec[1], ob);
|
|
|
|
td++;
|
|
|
|
|
|
|
|
TimeToTransData(td, bezt->vec[2], ob);
|
|
|
|
td++;
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return td;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void createTransActionData(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
Object *ob= NULL;
|
|
|
|
|
|
|
|
ListBase act_data = {NULL, NULL};
|
|
|
|
bActListElem *ale;
|
|
|
|
void *data;
|
|
|
|
short datatype;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
int count=0;
|
2007-11-06 11:41:09 +00:00
|
|
|
float cfra;
|
|
|
|
char side;
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* determine what type of data we are operating on */
|
|
|
|
data = get_action_context(&datatype);
|
|
|
|
if (data == NULL) return;
|
|
|
|
|
|
|
|
/* filter data */
|
|
|
|
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
|
|
|
|
actdata_filter(&act_data, filter, data, datatype);
|
|
|
|
|
|
|
|
/* is the action scaled? if so, the it should belong to the active object */
|
|
|
|
if (NLA_ACTION_SCALED)
|
|
|
|
ob= OBACT;
|
2007-11-06 11:41:09 +00:00
|
|
|
|
|
|
|
/* which side of the current frame should be allowed */
|
|
|
|
if (t->mode == TFM_TIME_EXTEND) {
|
|
|
|
/* only side on which mouse is gets transformed */
|
|
|
|
float xmouse, ymouse;
|
|
|
|
|
|
|
|
areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
|
|
|
|
side = (xmouse > CFRA) ? 'R' : 'L';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* normal transform - both sides of current frame are considered */
|
|
|
|
side = 'B';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert current-frame to action-time (slightly less accurate, espcially under
|
|
|
|
* higher scaling ratios, but is faster than converting all points)
|
|
|
|
*/
|
|
|
|
if (ob)
|
|
|
|
cfra = get_action_frame(ob, CFRA);
|
|
|
|
else
|
|
|
|
cfra = CFRA;
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
|
|
|
|
for (ale= act_data.first; ale; ale= ale->next)
|
2007-11-06 11:41:09 +00:00
|
|
|
count += count_ipo_keys(ale->key_data, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* stop if trying to build list if nothing selected */
|
|
|
|
if (count == 0) {
|
|
|
|
/* cleanup temp list */
|
|
|
|
BLI_freelistN(&act_data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate memory for data */
|
|
|
|
t->total= count;
|
|
|
|
t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
|
|
|
|
if (t->mode == TFM_TIME_SLIDE)
|
|
|
|
t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
|
|
|
|
|
|
|
|
td= t->data;
|
|
|
|
/* loop 2: build transdata array */
|
|
|
|
for (ale= act_data.first; ale; ale= ale->next) {
|
|
|
|
Ipo *ipo= (Ipo *)ale->key_data;
|
|
|
|
|
2007-11-06 11:41:09 +00:00
|
|
|
td= IpoToTransData(td, ipo, ob, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check if we're supposed to be setting minx/maxx for TimeSlide */
|
|
|
|
if (t->mode == TFM_TIME_SLIDE) {
|
|
|
|
float min = 0, max = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
td= (t->data + 1);
|
|
|
|
for (i=1; i < count; i+=3, td+=3) {
|
|
|
|
if (min > *(td->val)) min= *(td->val);
|
|
|
|
if (max < *(td->val)) max= *(td->val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* minx/maxx values used by TimeSlide are stored as a
|
|
|
|
* calloced 2-float array in t->customData. This gets freed
|
|
|
|
* in postTrans (T_FREE_CUSTOMDATA).
|
|
|
|
*/
|
|
|
|
*((float *)(t->customData)) = min;
|
2007-09-25 00:05:53 +00:00
|
|
|
*((float *)(t->customData) + 1) = max;
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* cleanup temp list */
|
|
|
|
BLI_freelistN(&act_data);
|
|
|
|
}
|
|
|
|
|
2007-09-30 11:43:16 +00:00
|
|
|
static void createTransNlaData(TransInfo *t)
|
2007-09-24 11:29:25 +00:00
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
bActionStrip *strip;
|
|
|
|
bActionChannel *achan;
|
|
|
|
bConstraintChannel *conchan;
|
|
|
|
|
|
|
|
TransData *td = NULL;
|
|
|
|
int count=0, i;
|
2007-11-06 11:41:09 +00:00
|
|
|
float cfra;
|
|
|
|
char side;
|
|
|
|
|
|
|
|
/* which side of the current frame should be allowed */
|
|
|
|
if (t->mode == TFM_TIME_EXTEND) {
|
|
|
|
/* only side on which mouse is gets transformed */
|
|
|
|
float xmouse, ymouse;
|
|
|
|
|
|
|
|
areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
|
|
|
|
side = (xmouse > CFRA) ? 'R' : 'L';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* normal transform - both sides of current frame are considered */
|
|
|
|
side = 'B';
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* Ensure that partial selections result in beztriple selections */
|
|
|
|
for (base=G.scene->base.first; base; base=base->next) {
|
|
|
|
/* Check object ipos */
|
2007-11-06 11:41:09 +00:00
|
|
|
i= count_ipo_keys(base->object->ipo, side, CFRA);
|
2007-09-24 11:29:25 +00:00
|
|
|
if (i) base->flag |= BA_HAS_RECALC_OB;
|
|
|
|
count += i;
|
|
|
|
|
|
|
|
/* Check object constraint ipos */
|
|
|
|
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
2007-11-06 11:41:09 +00:00
|
|
|
count += count_ipo_keys(conchan->ipo, side, CFRA);
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* skip actions and nlastrips if object is collapsed */
|
|
|
|
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Check action ipos */
|
|
|
|
if (base->object->action) {
|
|
|
|
/* exclude if strip is selected too */
|
|
|
|
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
|
|
|
if (strip->flag & ACTSTRIP_SELECT)
|
|
|
|
if (strip->act == base->object->action)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strip==NULL) {
|
2007-11-06 11:41:09 +00:00
|
|
|
cfra = get_action_frame(base->object, CFRA);
|
|
|
|
|
2007-09-24 11:29:25 +00:00
|
|
|
for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
|
|
|
|
if (EDITABLE_ACHAN(achan)) {
|
2007-11-06 11:41:09 +00:00
|
|
|
i= count_ipo_keys(achan->ipo, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
|
|
|
count += i;
|
|
|
|
|
|
|
|
/* Check action constraint ipos */
|
|
|
|
if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
|
|
|
|
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
|
|
|
|
if (EDITABLE_CONCHAN(conchan))
|
2007-11-06 11:41:09 +00:00
|
|
|
count += count_ipo_keys(conchan->ipo, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check nlastrips */
|
|
|
|
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
|
|
|
if (strip->flag & ACTSTRIP_SELECT) {
|
|
|
|
base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
|
2007-11-06 11:41:09 +00:00
|
|
|
|
|
|
|
if (FrameOnMouseSide(side, strip->start, CFRA)) count++;
|
|
|
|
if (FrameOnMouseSide(side, strip->end, CFRA)) count++;
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If nothing is selected, bail out */
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* allocate memory for data */
|
|
|
|
t->total= count;
|
|
|
|
t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
|
|
|
|
|
|
|
|
/* build the transdata structure */
|
|
|
|
td= t->data;
|
|
|
|
for (base=G.scene->base.first; base; base=base->next) {
|
|
|
|
/* Manipulate object ipos */
|
|
|
|
/* - no scaling of keyframe times is allowed here */
|
2007-11-06 11:41:09 +00:00
|
|
|
td= IpoToTransData(td, base->object->ipo, NULL, side, CFRA);
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* Manipulate object constraint ipos */
|
|
|
|
/* - no scaling of keyframe times is allowed here */
|
|
|
|
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
2007-11-06 11:41:09 +00:00
|
|
|
td= IpoToTransData(td, conchan->ipo, NULL, side, CFRA);
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* skip actions and nlastrips if object collapsed */
|
|
|
|
if (base->object->nlaflag & OB_NLA_COLLAPSED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Manipulate action ipos */
|
|
|
|
if (base->object->action) {
|
|
|
|
/* exclude if strip that active action belongs to is selected too */
|
|
|
|
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
|
|
|
if (strip->flag & ACTSTRIP_SELECT)
|
|
|
|
if (strip->act == base->object->action)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* can include if no strip found */
|
|
|
|
if (strip==NULL) {
|
2007-11-06 11:41:09 +00:00
|
|
|
cfra = get_action_frame(base->object, CFRA);
|
|
|
|
|
2007-09-24 11:29:25 +00:00
|
|
|
for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
|
|
|
|
if (EDITABLE_ACHAN(achan)) {
|
2007-11-06 11:41:09 +00:00
|
|
|
td= IpoToTransData(td, achan->ipo, base->object, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
|
|
|
|
/* Manipulate action constraint ipos */
|
|
|
|
if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
|
|
|
|
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
|
|
|
|
if (EDITABLE_CONCHAN(conchan))
|
2007-11-06 11:41:09 +00:00
|
|
|
td= IpoToTransData(td, conchan->ipo, base->object, side, cfra);
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Manipulate nlastrips */
|
|
|
|
for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
|
|
|
|
if (strip->flag & ACTSTRIP_SELECT) {
|
|
|
|
/* first TransData is the start, second is the end */
|
2007-11-06 11:41:09 +00:00
|
|
|
if (FrameOnMouseSide(side, strip->start, CFRA)) {
|
|
|
|
td->val = &strip->start;
|
|
|
|
td->ival = strip->start;
|
|
|
|
td++;
|
|
|
|
}
|
|
|
|
if (FrameOnMouseSide(side, strip->end, CFRA)) {
|
|
|
|
td->val = &strip->end;
|
|
|
|
td->ival = strip->end;
|
|
|
|
td++;
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* **************** IpoKey stuff, for Object TransData ********** */
|
|
|
|
|
|
|
|
/* storage of bezier triple. thats why -3 and +3! */
|
|
|
|
static void set_tdi_old(float *old, float *poin)
|
|
|
|
{
|
|
|
|
old[0]= *(poin);
|
|
|
|
old[3]= *(poin-3);
|
|
|
|
old[6]= *(poin+3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* while transforming */
|
|
|
|
void add_tdi_poin(float *poin, float *old, float delta)
|
|
|
|
{
|
|
|
|
if(poin) {
|
|
|
|
poin[0]= old[0]+delta;
|
|
|
|
poin[-3]= old[3]+delta;
|
|
|
|
poin[3]= old[6]+delta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill ipokey transdata with old vals and pointers */
|
|
|
|
static void ipokey_to_transdata(IpoKey *ik, TransData *td)
|
|
|
|
{
|
|
|
|
extern int ob_ar[]; // blenkernel ipo.c
|
|
|
|
TransDataIpokey *tdi= td->tdi;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int a, delta= 0;
|
|
|
|
|
2005-05-08 20:44:59 +00:00
|
|
|
td->val= NULL; // is read on ESC
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
for(a=0; a<OB_TOTIPO; a++) {
|
|
|
|
if(ik->data[a]) {
|
|
|
|
bezt= ik->data[a];
|
|
|
|
|
|
|
|
switch( ob_ar[a] ) {
|
|
|
|
case OB_LOC_X:
|
|
|
|
case OB_DLOC_X:
|
|
|
|
tdi->locx= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_LOC_Y:
|
|
|
|
case OB_DLOC_Y:
|
|
|
|
tdi->locy= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_LOC_Z:
|
|
|
|
case OB_DLOC_Z:
|
|
|
|
tdi->locz= &(bezt->vec[1][1]); break;
|
|
|
|
|
|
|
|
case OB_DROT_X:
|
|
|
|
delta= 1;
|
|
|
|
case OB_ROT_X:
|
|
|
|
tdi->rotx= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_DROT_Y:
|
|
|
|
delta= 1;
|
|
|
|
case OB_ROT_Y:
|
|
|
|
tdi->roty= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_DROT_Z:
|
|
|
|
delta= 1;
|
|
|
|
case OB_ROT_Z:
|
|
|
|
tdi->rotz= &(bezt->vec[1][1]); break;
|
|
|
|
|
|
|
|
case OB_SIZE_X:
|
|
|
|
case OB_DSIZE_X:
|
|
|
|
tdi->sizex= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_SIZE_Y:
|
|
|
|
case OB_DSIZE_Y:
|
|
|
|
tdi->sizey= &(bezt->vec[1][1]); break;
|
|
|
|
case OB_SIZE_Z:
|
|
|
|
case OB_DSIZE_Z:
|
|
|
|
tdi->sizez= &(bezt->vec[1][1]); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* oldvals for e.g. undo */
|
|
|
|
if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
|
|
|
|
if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
|
|
|
|
if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
|
|
|
|
|
|
|
|
/* remember, for mapping curves ('1'=10 degrees) */
|
|
|
|
if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
|
|
|
|
if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
|
|
|
|
if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
|
|
|
|
|
|
|
|
/* this is not allowed to be dsize! */
|
|
|
|
if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
|
|
|
|
if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
|
|
|
|
if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
|
|
|
|
|
|
|
|
tdi->flag= TOB_IPO;
|
|
|
|
if(delta) tdi->flag |= TOB_IPODROT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* *************************** Object Transform data ******************* */
|
|
|
|
|
2007-07-24 11:39:40 +00:00
|
|
|
/* Little helper function for ObjectToTransData used to give certain
|
|
|
|
* constraints (ChildOf, FollowPath, and others that may be added)
|
|
|
|
* inverse corrections for transform, so that they aren't in CrazySpace.
|
|
|
|
* These particular constraints benefit from this, but others don't, hence
|
|
|
|
* this semi-hack ;-) - Aligorith
|
|
|
|
*/
|
2007-11-10 02:53:19 +00:00
|
|
|
static short constraints_list_needinv(TransInfo *t, ListBase *list)
|
2007-07-24 11:39:40 +00:00
|
|
|
{
|
|
|
|
bConstraint *con;
|
|
|
|
|
|
|
|
/* loop through constraints, checking if there's one of the mentioned
|
|
|
|
* constraints needing special crazyspace corrections
|
|
|
|
*/
|
2007-07-24 12:15:23 +00:00
|
|
|
if (list) {
|
|
|
|
for (con= list->first; con; con=con->next) {
|
2007-07-24 11:39:40 +00:00
|
|
|
/* only consider constraint if it is enabled, and has influence on result */
|
|
|
|
if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
|
|
|
|
/* (affirmative) returns for specific constraints here... */
|
2007-11-10 02:53:19 +00:00
|
|
|
/* constraints that require this regardless */
|
2007-07-24 11:39:40 +00:00
|
|
|
if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
|
|
|
|
if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
|
|
|
|
if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
|
2007-11-10 02:53:19 +00:00
|
|
|
|
|
|
|
/* constraints that require this only under special conditions */
|
|
|
|
if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
|
|
|
|
/* CopyRot constraint only does this when rotating, and offset is on */
|
|
|
|
bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
|
|
|
|
|
|
|
|
if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
|
|
|
|
return 1;
|
|
|
|
}
|
2007-07-24 11:39:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no appropriate candidates found */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* transcribe given object into TransData for Transforming */
|
2007-11-10 02:53:19 +00:00
|
|
|
static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
|
2005-04-10 18:33:19 +00:00
|
|
|
{
|
2007-07-25 11:38:50 +00:00
|
|
|
Object *track;
|
2007-07-27 05:03:57 +00:00
|
|
|
ListBase fakecons = {NULL, NULL};
|
2005-04-10 18:33:19 +00:00
|
|
|
float obmtx[3][3];
|
2007-07-27 05:03:57 +00:00
|
|
|
short constinv;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
== Constraints System ==
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
2007-07-15 03:35:37 +00:00
|
|
|
/* axismtx has the real orientation */
|
2005-06-06 12:23:47 +00:00
|
|
|
Mat3CpyMat4(td->axismtx, ob->obmat);
|
|
|
|
Mat3Ortho(td->axismtx);
|
|
|
|
|
2007-12-05 11:19:36 +00:00
|
|
|
td->con= ob->constraints.first;
|
|
|
|
|
2007-07-27 05:03:57 +00:00
|
|
|
/* hack: tempolarily disable tracking and/or constraints when getting
|
|
|
|
* object matrix, if tracking is on, or if constraints don't need
|
|
|
|
* inverse correction to stop it from screwing up space conversion
|
|
|
|
* matrix later
|
2007-07-25 11:38:50 +00:00
|
|
|
*/
|
2007-11-10 02:53:19 +00:00
|
|
|
constinv= constraints_list_needinv(t, &ob->constraints);
|
2007-07-27 05:03:57 +00:00
|
|
|
if (ob->track || constinv==0) {
|
2007-07-25 11:38:50 +00:00
|
|
|
track= ob->track;
|
|
|
|
ob->track= NULL;
|
|
|
|
|
2007-07-27 05:03:57 +00:00
|
|
|
if (constinv == 0) {
|
|
|
|
fakecons.first = ob->constraints.first;
|
|
|
|
fakecons.last = ob->constraints.last;
|
|
|
|
ob->constraints.first = ob->constraints.last = NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-25 11:38:50 +00:00
|
|
|
where_is_object(ob);
|
|
|
|
|
2007-07-27 05:03:57 +00:00
|
|
|
if (constinv == 0) {
|
|
|
|
ob->constraints.first = fakecons.first;
|
|
|
|
ob->constraints.last = fakecons.last;
|
|
|
|
}
|
|
|
|
|
2007-07-25 11:38:50 +00:00
|
|
|
ob->track= track;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
where_is_object(ob);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
td->ob = ob;
|
|
|
|
|
|
|
|
td->loc = ob->loc;
|
|
|
|
VECCOPY(td->iloc, td->loc);
|
|
|
|
|
|
|
|
td->ext->rot = ob->rot;
|
|
|
|
VECCOPY(td->ext->irot, ob->rot);
|
|
|
|
VECCOPY(td->ext->drot, ob->drot);
|
|
|
|
|
|
|
|
td->ext->size = ob->size;
|
|
|
|
VECCOPY(td->ext->isize, ob->size);
|
|
|
|
VECCOPY(td->ext->dsize, ob->dsize);
|
|
|
|
|
|
|
|
VECCOPY(td->center, ob->obmat[3]);
|
2008-01-13 22:20:18 +00:00
|
|
|
|
|
|
|
Mat4CpyMat4(td->ext->obmat, ob->obmat);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2007-07-24 11:39:40 +00:00
|
|
|
/* is there a need to set the global<->data space conversion matrices? */
|
2007-07-27 05:03:57 +00:00
|
|
|
if (ob->parent || constinv) {
|
2005-04-10 18:33:19 +00:00
|
|
|
float totmat[3][3], obinv[3][3];
|
|
|
|
|
2007-07-24 11:39:40 +00:00
|
|
|
/* Get the effect of parenting, and/or certain constraints.
|
|
|
|
* NOTE: some Constraints, and also Tracking should never get this
|
|
|
|
* done, as it doesn't work well.
|
|
|
|
*/
|
2005-04-10 18:33:19 +00:00
|
|
|
object_to_mat3(ob, obmtx);
|
|
|
|
Mat3CpyMat4(totmat, ob->obmat);
|
2007-07-24 11:39:40 +00:00
|
|
|
Mat3Inv(obinv, totmat);
|
|
|
|
Mat3MulMat3(td->smtx, obmtx, obinv);
|
2005-04-10 18:33:19 +00:00
|
|
|
Mat3Inv(td->mtx, td->smtx);
|
|
|
|
}
|
2007-07-24 11:39:40 +00:00
|
|
|
else {
|
|
|
|
/* no conversion to/from dataspace */
|
2005-04-10 18:33:19 +00:00
|
|
|
Mat3One(td->smtx);
|
|
|
|
Mat3One(td->mtx);
|
|
|
|
}
|
2008-01-20 22:43:48 +00:00
|
|
|
|
|
|
|
/* set active flag */
|
|
|
|
if (BASACT && BASACT->object == ob)
|
|
|
|
{
|
|
|
|
td->flag |= TD_ACTIVE;
|
|
|
|
}
|
|
|
|
|
2006-08-20 15:22:56 +00:00
|
|
|
#ifdef WITH_VERSE
|
|
|
|
if(ob->vnode) {
|
|
|
|
td->verse = (void*)ob;
|
|
|
|
td->flag |= TD_VERSE_OBJECT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
td->flag &= ~TD_VERSE_OBJECT;
|
|
|
|
#endif
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* sets flags in Bases to define whether they take part in transform */
|
|
|
|
/* it deselects Bases, so we have to call the clear function always after */
|
|
|
|
static void set_trans_object_base_flags(TransInfo *t)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
if Base selected and has parent selected:
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
base->flag= BA_WAS_SEL
|
2005-04-10 18:33:19 +00:00
|
|
|
*/
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
/* makes sure base flags and object flags are identical */
|
|
|
|
copy_baseflags();
|
|
|
|
|
2005-09-26 15:34:21 +00:00
|
|
|
/* handle pending update events, otherwise they got copied below */
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base->object->recalc)
|
|
|
|
object_handle_update(base->object);
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
base->flag &= ~BA_WAS_SEL;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
if(TESTBASELIB(base)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
Object *ob= base->object;
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
Object *parsel= ob->parent;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
/* if parent selected, deselect */
|
|
|
|
while(parsel) {
|
|
|
|
if(parsel->flag & SELECT) break;
|
|
|
|
parsel= parsel->parent;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
if(parsel) {
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
base->flag |= BA_WAS_SEL;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
/* used for flush, depgraph will change recalcs if needed :) */
|
|
|
|
ob->recalc |= OB_RECALC_OB;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-16 13:06:09 +00:00
|
|
|
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
|
|
|
|
DAG_scene_flush_update(G.scene, -1);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
/* and we store them temporal in base (only used for transform code) */
|
|
|
|
/* this because after doing updates, the object->recalc is cleared */
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base->object->recalc & OB_RECALC_OB)
|
|
|
|
base->flag |= BA_HAS_RECALC_OB;
|
|
|
|
if(base->object->recalc & OB_RECALC_DATA)
|
|
|
|
base->flag |= BA_HAS_RECALC_DATA;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
2005-07-19 11:21:01 +00:00
|
|
|
static void clear_trans_object_base_flags(void)
|
2005-04-10 18:33:19 +00:00
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
base= FIRSTBASE;
|
|
|
|
while(base) {
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
|
|
|
|
base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-07-04 05:16:54 +00:00
|
|
|
base = base->next;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
/* auto-keyframing feature - checks for whether anything should be done for the current frame */
|
|
|
|
short autokeyframe_cfra_can_key(Object *ob)
|
|
|
|
{
|
|
|
|
ListBase keys = {NULL, NULL};
|
|
|
|
ActKeyColumn *ak;
|
|
|
|
float cfra;
|
|
|
|
short found= 0;
|
|
|
|
|
|
|
|
/* only filter if auto-key mode requires this */
|
2008-01-12 11:06:51 +00:00
|
|
|
if (IS_AUTOKEY_ON == 0)
|
2008-01-10 01:36:22 +00:00
|
|
|
return 0;
|
|
|
|
else if (IS_AUTOKEY_MODE(NORMAL))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* sanity check */
|
|
|
|
if (ob == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* get keyframes that object has (bone anim is stored on ob too) */
|
|
|
|
if (ob->action)
|
2008-01-27 03:21:24 +00:00
|
|
|
action_to_keylist(ob->action, &keys, NULL, NULL);
|
2008-01-10 01:36:22 +00:00
|
|
|
else if (ob->ipo)
|
2008-01-27 03:21:24 +00:00
|
|
|
ipo_to_keylist(ob->ipo, &keys, NULL, NULL);
|
2008-01-10 01:36:22 +00:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* get current frame (will apply nla-scaling as necessary) */
|
|
|
|
// ack... this is messy...
|
|
|
|
cfra= frame_to_float(CFRA);
|
|
|
|
cfra= get_action_frame(ob, cfra);
|
|
|
|
|
|
|
|
/* check if a keyframe occurs on current frame */
|
|
|
|
for (ak= keys.first; ak; ak= ak->next) {
|
|
|
|
if (IS_EQ(cfra, ak->cfra)) {
|
|
|
|
found= 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free temp list */
|
|
|
|
BLI_freelistN(&keys);
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2007-06-23 06:56:16 +00:00
|
|
|
/* auto-keyframing feature - for objects
|
|
|
|
* tmode: should be a transform mode
|
|
|
|
*/
|
|
|
|
void autokeyframe_ob_cb_func(Object *ob, int tmode)
|
|
|
|
{
|
|
|
|
IpoCurve *icu;
|
|
|
|
char *actname="";
|
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
if (autokeyframe_cfra_can_key(ob)) {
|
2007-11-21 04:08:00 +00:00
|
|
|
if (ob->ipoflag & OB_ACTION_OB)
|
2007-06-23 06:56:16 +00:00
|
|
|
actname= "Object";
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
|
2007-11-21 04:08:00 +00:00
|
|
|
if (ob->ipo || ob->action) {
|
2007-06-23 06:56:16 +00:00
|
|
|
ID *id= (ID *)(ob);
|
|
|
|
|
|
|
|
if (ob->ipo) {
|
|
|
|
icu= ob->ipo->curve.first;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bActionChannel *achan;
|
|
|
|
achan= get_action_channel(ob->action, actname);
|
|
|
|
|
|
|
|
if (achan && achan->ipo)
|
|
|
|
icu= achan->ipo->curve.first;
|
|
|
|
else
|
|
|
|
icu= NULL;
|
|
|
|
}
|
|
|
|
|
2007-11-21 04:08:00 +00:00
|
|
|
while (icu) {
|
2007-06-23 06:56:16 +00:00
|
|
|
icu->flag &= ~IPO_SELECT;
|
2008-01-10 01:36:22 +00:00
|
|
|
if (IS_AUTOKEY_FLAG(INSERTNEEDED))
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
|
|
|
|
else
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0);
|
2007-06-23 06:56:16 +00:00
|
|
|
icu= icu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-10 01:36:22 +00:00
|
|
|
else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) {
|
2007-11-21 04:08:00 +00:00
|
|
|
short doLoc=0, doRot=0, doScale=0;
|
|
|
|
|
|
|
|
/* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
|
|
|
|
if (tmode == TFM_TRANSLATION) {
|
|
|
|
doLoc = 1;
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (tmode == TFM_ROTATION) {
|
|
|
|
if (G.vd->around == V3D_ACTIVE) {
|
|
|
|
if (ob != OBACT)
|
|
|
|
doLoc = 1;
|
|
|
|
}
|
|
|
|
else if (G.vd->around == V3D_CURSOR)
|
|
|
|
doLoc = 1;
|
|
|
|
|
|
|
|
if ((G.vd->flag & V3D_ALIGN)==0)
|
|
|
|
doRot = 1;
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (tmode == TFM_RESIZE) {
|
|
|
|
if (G.vd->around == V3D_ACTIVE) {
|
|
|
|
if (ob != OBACT)
|
|
|
|
doLoc = 1;
|
|
|
|
}
|
|
|
|
else if (G.vd->around == V3D_CURSOR)
|
|
|
|
doLoc = 1;
|
|
|
|
|
|
|
|
if ((G.vd->flag & V3D_ALIGN)==0)
|
|
|
|
doScale = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doLoc) {
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
if (doRot) {
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
|
|
|
|
}
|
|
|
|
if (doScale) {
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
|
|
|
|
}
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z, 0);
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z, 0);
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z, 0);
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2007-06-23 06:56:16 +00:00
|
|
|
remake_object_ipos(ob);
|
2007-10-17 15:27:38 +00:00
|
|
|
allqueue(REDRAWMARKER, 0);
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auto-keyframing feature - for poses/pose-channels
|
|
|
|
* tmode: should be a transform mode
|
|
|
|
* targetless_ik: has targetless ik been done on any channels?
|
|
|
|
*/
|
|
|
|
void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
|
|
|
|
{
|
2007-11-14 16:50:51 +00:00
|
|
|
bArmature *arm= ob->data;
|
2007-06-23 06:56:16 +00:00
|
|
|
bAction *act;
|
|
|
|
bPose *pose;
|
|
|
|
bPoseChannel *pchan;
|
|
|
|
IpoCurve *icu;
|
|
|
|
|
|
|
|
pose= ob->pose;
|
|
|
|
act= ob->action;
|
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
if (autokeyframe_cfra_can_key(ob)) {
|
|
|
|
if (act == NULL)
|
2007-06-23 06:56:16 +00:00
|
|
|
act= ob->action= add_empty_action("Action");
|
|
|
|
|
2007-09-25 05:04:34 +00:00
|
|
|
for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
|
|
|
|
if (pchan->bone->flag & BONE_TRANSFORM) {
|
|
|
|
/* clear any 'unkeyed' flag it may have */
|
|
|
|
pchan->bone->flag &= ~BONE_UNKEYED;
|
|
|
|
|
|
|
|
/* only insert into available channels? */
|
2008-01-10 01:36:22 +00:00
|
|
|
if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
|
2007-06-23 06:56:16 +00:00
|
|
|
bActionChannel *achan;
|
2007-09-25 05:04:34 +00:00
|
|
|
|
2008-01-10 01:36:22 +00:00
|
|
|
for (achan = act->chanbase.first; achan; achan=achan->next) {
|
|
|
|
if (achan->ipo && !strcmp (achan->name, pchan->name)) {
|
|
|
|
for (icu = achan->ipo->curve.first; icu; icu=icu->next) {
|
2007-09-25 05:04:34 +00:00
|
|
|
/* only insert keyframe if needed? */
|
2008-01-10 01:36:22 +00:00
|
|
|
if (IS_AUTOKEY_FLAG(INSERTNEEDED))
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
|
|
|
|
else
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0);
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-09-25 05:04:34 +00:00
|
|
|
/* only insert keyframe if needed? */
|
2008-01-10 01:36:22 +00:00
|
|
|
else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) {
|
2007-11-21 04:08:00 +00:00
|
|
|
short doLoc=0, doRot=0, doScale=0;
|
|
|
|
|
|
|
|
/* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
|
|
|
|
if (tmode == TFM_TRANSLATION) {
|
|
|
|
if (targetless_ik)
|
|
|
|
doRot= 1;
|
|
|
|
else
|
|
|
|
doLoc = 1;
|
|
|
|
}
|
|
|
|
else if (tmode == TFM_ROTATION) {
|
|
|
|
if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE))
|
|
|
|
doLoc = 1;
|
|
|
|
|
|
|
|
if ((G.vd->flag & V3D_ALIGN)==0)
|
|
|
|
doRot = 1;
|
|
|
|
}
|
|
|
|
else if (tmode == TFM_RESIZE) {
|
|
|
|
if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE))
|
|
|
|
doLoc = 1;
|
|
|
|
|
|
|
|
if ((G.vd->flag & V3D_ALIGN)==0)
|
|
|
|
doScale = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doLoc) {
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
if (doRot) {
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
if (doScale) {
|
2007-06-23 06:56:16 +00:00
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
|
|
|
|
insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
|
|
|
|
}
|
|
|
|
}
|
2007-09-25 05:04:34 +00:00
|
|
|
/* insert keyframe in any channel that's appropriate */
|
2007-06-23 06:56:16 +00:00
|
|
|
else {
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0);
|
2007-09-25 05:04:34 +00:00
|
|
|
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
|
2007-09-25 05:04:34 +00:00
|
|
|
|
2007-09-18 06:41:29 +00:00
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
|
|
|
|
insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
remake_action_ipos (act);
|
2007-10-17 15:27:38 +00:00
|
|
|
allqueue(REDRAWMARKER, 0);
|
2007-11-14 16:50:51 +00:00
|
|
|
|
|
|
|
/* locking can be disabled */
|
|
|
|
ob->pose->flag &= ~(POSE_DO_UNLOCK|POSE_LOCKED);
|
|
|
|
|
|
|
|
/* do the bone paths */
|
|
|
|
if (arm->pathflag & ARM_PATH_ACFRA) {
|
2007-12-01 11:57:16 +00:00
|
|
|
//pose_clear_paths(ob);
|
2007-12-04 11:34:26 +00:00
|
|
|
pose_recalculate_paths(ob);
|
2008-01-10 01:36:22 +00:00
|
|
|
}
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
2007-09-25 05:04:34 +00:00
|
|
|
else {
|
|
|
|
/* tag channels that should have unkeyed data */
|
|
|
|
for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
|
|
|
|
if (pchan->bone->flag & BONE_TRANSFORM) {
|
|
|
|
/* tag this channel */
|
|
|
|
pchan->bone->flag |= BONE_UNKEYED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-06-23 06:56:16 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 11:29:25 +00:00
|
|
|
/* very bad call!!! - copied from editnla.c! */
|
|
|
|
static void recalc_all_ipos(void)
|
|
|
|
{
|
|
|
|
Ipo *ipo;
|
|
|
|
IpoCurve *icu;
|
|
|
|
|
|
|
|
/* Go to each ipo */
|
|
|
|
for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
|
|
|
|
for (icu = ipo->curve.first; icu; icu=icu->next){
|
|
|
|
sort_time_ipocurve(icu);
|
|
|
|
testhandles_ipocurve(icu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
/* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
|
2007-09-24 11:29:25 +00:00
|
|
|
/* note: transdata has been freed already! */
|
2005-08-16 10:17:02 +00:00
|
|
|
void special_aftertrans_update(TransInfo *t)
|
2005-05-04 12:53:35 +00:00
|
|
|
{
|
2005-08-16 10:17:02 +00:00
|
|
|
Object *ob;
|
2005-05-04 12:53:35 +00:00
|
|
|
Base *base;
|
2007-10-17 08:23:08 +00:00
|
|
|
short redrawipo=0, resetslowpar=1;
|
2005-08-16 10:17:02 +00:00
|
|
|
int cancelled= (t->state == TRANS_CANCEL);
|
2007-10-18 21:47:55 +00:00
|
|
|
|
2008-03-07 22:01:52 +00:00
|
|
|
if (t->spacetype==SPACE_VIEW3D) {
|
2007-10-18 21:47:55 +00:00
|
|
|
EM_automerge(1);
|
2008-03-07 22:01:52 +00:00
|
|
|
/* when snapping, delay retopo until after automerge */
|
|
|
|
if (G.qual & LR_CTRLKEY) {
|
|
|
|
retopo_do_all();
|
|
|
|
}
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
if (t->spacetype == SPACE_ACTION) {
|
2007-09-24 11:29:25 +00:00
|
|
|
void *data;
|
|
|
|
short datatype;
|
|
|
|
|
|
|
|
/* determine what type of data we are operating on */
|
|
|
|
data = get_action_context(&datatype);
|
|
|
|
if (data == NULL) return;
|
|
|
|
ob = OBACT;
|
|
|
|
|
|
|
|
if (datatype == ACTCONT_ACTION) {
|
|
|
|
/* Depending on the lock status, draw necessary views */
|
|
|
|
if (ob) {
|
|
|
|
ob->ctime= -1234567.0f;
|
|
|
|
|
|
|
|
if(ob->pose || ob_get_key(ob))
|
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
|
|
|
else
|
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
|
|
}
|
|
|
|
|
2008-01-28 11:38:12 +00:00
|
|
|
/* Do curve cleanups? */
|
2008-02-04 01:30:44 +00:00
|
|
|
if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
|
|
|
|
(cancelled == 0) )
|
|
|
|
{
|
2008-01-28 11:38:12 +00:00
|
|
|
posttrans_action_clean((bAction *)data);
|
2008-02-04 01:30:44 +00:00
|
|
|
}
|
2008-01-28 11:38:12 +00:00
|
|
|
|
2008-02-06 23:27:03 +00:00
|
|
|
/* Do curve updates */
|
|
|
|
remake_action_ipos((bAction *)data);
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
else if (datatype == ACTCONT_SHAPEKEY) {
|
|
|
|
/* fix up the Ipocurves and redraw stuff */
|
|
|
|
Key *key= (Key *)data;
|
|
|
|
if (key->ipo) {
|
|
|
|
IpoCurve *icu;
|
|
|
|
|
2008-02-06 23:27:03 +00:00
|
|
|
|
2008-01-28 11:38:12 +00:00
|
|
|
|
2008-02-04 01:30:44 +00:00
|
|
|
if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
|
|
|
|
(cancelled == 0) )
|
|
|
|
{
|
2008-01-28 11:38:12 +00:00
|
|
|
posttrans_ipo_clean(key->ipo);
|
2008-02-04 01:30:44 +00:00
|
|
|
}
|
2008-02-06 23:27:03 +00:00
|
|
|
|
|
|
|
for (icu = key->ipo->curve.first; icu; icu=icu->next) {
|
|
|
|
sort_time_ipocurve(icu);
|
|
|
|
testhandles_ipocurve(icu);
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
|
|
|
}
|
2008-02-17 06:00:18 +00:00
|
|
|
|
|
|
|
G.saction->flag &= ~SACTION_MOVING;
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (t->spacetype == SPACE_NLA) {
|
2007-09-24 11:29:25 +00:00
|
|
|
synchronize_action_strips();
|
2007-10-17 08:23:08 +00:00
|
|
|
|
2007-09-24 11:29:25 +00:00
|
|
|
/* cleanup */
|
|
|
|
for (base=G.scene->base.first; base; base=base->next)
|
|
|
|
base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
|
|
|
|
|
|
|
|
recalc_all_ipos(); // bad
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (t->spacetype == SPACE_IPO) {
|
2007-10-17 08:23:08 +00:00
|
|
|
// FIXME! is there any code from the old transform_ipo that needs to be added back?
|
|
|
|
|
|
|
|
/* resetting slow-parents isn't really necessary when editing sequence ipo's */
|
|
|
|
if (G.sipo->blocktype==ID_SEQ)
|
|
|
|
resetslowpar= 0;
|
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (G.obedit) {
|
|
|
|
if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
2005-12-01 19:04:57 +00:00
|
|
|
|
|
|
|
/* table needs to be created for each edit command, since vertices can move etc */
|
|
|
|
mesh_octree_table(G.obedit, NULL, 'e');
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if ((t->flag & T_POSE) && (t->poseobj)) {
|
2005-08-16 10:17:02 +00:00
|
|
|
bArmature *arm;
|
2005-05-04 12:53:35 +00:00
|
|
|
bPose *pose;
|
|
|
|
bPoseChannel *pchan;
|
2007-04-06 10:24:14 +00:00
|
|
|
short targetless_ik= 0;
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2005-08-16 10:17:02 +00:00
|
|
|
ob= t->poseobj;
|
|
|
|
arm= ob->data;
|
2005-10-30 13:50:42 +00:00
|
|
|
pose= ob->pose;
|
2005-08-16 10:17:02 +00:00
|
|
|
|
2005-10-22 18:47:38 +00:00
|
|
|
/* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
|
2005-10-30 13:50:42 +00:00
|
|
|
pose->flag |= POSE_DO_UNLOCK;
|
2007-11-21 04:08:00 +00:00
|
|
|
|
2005-10-30 13:50:42 +00:00
|
|
|
/* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
|
2007-11-21 04:08:00 +00:00
|
|
|
if (!cancelled && t->mode==TFM_TRANSLATION)
|
2007-04-06 10:24:14 +00:00
|
|
|
targetless_ik= apply_targetless_ik(ob);
|
2005-11-15 15:54:57 +00:00
|
|
|
else {
|
|
|
|
/* not forget to clear the auto flag */
|
|
|
|
for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
|
|
|
|
bKinematicConstraint *data= has_targetless_ik(pchan);
|
|
|
|
if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
|
|
|
|
}
|
|
|
|
}
|
2005-10-30 13:50:42 +00:00
|
|
|
|
2007-11-21 04:08:00 +00:00
|
|
|
if (t->mode==TFM_TRANSLATION)
|
2005-10-30 13:50:42 +00:00
|
|
|
pose_grab_with_ik_clear(ob);
|
2007-09-25 05:04:34 +00:00
|
|
|
|
2007-10-10 10:22:43 +00:00
|
|
|
/* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */
|
2007-11-21 04:08:00 +00:00
|
|
|
if (!cancelled && (t->mode != TFM_DUMMY)) {
|
2007-06-23 06:56:16 +00:00
|
|
|
autokeyframe_pose_cb_func(ob, t->mode, targetless_ik);
|
2005-07-23 18:52:31 +00:00
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
2005-05-04 12:53:35 +00:00
|
|
|
}
|
2007-11-21 04:08:00 +00:00
|
|
|
else if (arm->flag & ARM_DELAYDEFORM) {
|
2005-07-11 13:59:02 +00:00
|
|
|
/* old optimize trick... this enforces to bypass the depgraph */
|
2005-07-23 18:52:31 +00:00
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
|
|
ob->recalc= 0; // is set on OK position already by recalcData()
|
2005-07-11 13:59:02 +00:00
|
|
|
}
|
2005-10-22 18:47:38 +00:00
|
|
|
else
|
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
|
2007-11-21 04:08:00 +00:00
|
|
|
if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
2007-10-17 08:23:08 +00:00
|
|
|
|
2005-05-04 12:53:35 +00:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
else if(G.f & G_PARTICLEEDIT) {
|
|
|
|
;
|
2005-05-04 12:53:35 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
base= FIRSTBASE;
|
2008-01-29 21:01:12 +00:00
|
|
|
|
|
|
|
while (base) {
|
|
|
|
|
2005-05-04 12:53:35 +00:00
|
|
|
if(base->flag & BA_DO_IPO) redrawipo= 1;
|
2005-07-19 11:21:01 +00:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
ob= base->object;
|
2007-10-10 10:22:43 +00:00
|
|
|
|
2007-11-21 04:08:00 +00:00
|
|
|
if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
|
2008-01-29 21:01:12 +00:00
|
|
|
else if((ob == OBACT) && modifiers_isClothEnabled(ob)) {
|
|
|
|
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
|
|
|
if(clmd)
|
|
|
|
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
|
|
|
|
}
|
2005-05-04 12:53:35 +00:00
|
|
|
|
|
|
|
/* Set autokey if necessary */
|
2007-10-10 10:22:43 +00:00
|
|
|
if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {
|
2007-06-23 06:56:16 +00:00
|
|
|
autokeyframe_ob_cb_func(ob, t->mode);
|
2005-05-04 12:53:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2005-07-19 11:21:01 +00:00
|
|
|
clear_trans_object_base_flags();
|
|
|
|
|
2007-11-21 04:08:00 +00:00
|
|
|
if (redrawipo) {
|
2005-05-04 12:53:35 +00:00
|
|
|
allqueue(REDRAWNLA, 0);
|
|
|
|
allqueue(REDRAWACTION, 0);
|
|
|
|
allqueue(REDRAWIPO, 0);
|
|
|
|
}
|
|
|
|
|
2007-10-17 08:23:08 +00:00
|
|
|
if(resetslowpar)
|
|
|
|
reset_slowparents();
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
|
|
|
|
/* note; should actually only be done for all objects when a lamp is moved... (ton) */
|
2005-08-23 18:13:30 +00:00
|
|
|
if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
|
|
|
|
reshadeall_displist();
|
2005-05-04 12:53:35 +00:00
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
static void createTransObject(TransInfo *t)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
TransDataExtension *tx;
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
IpoKey *ik;
|
|
|
|
ListBase elems;
|
|
|
|
|
|
|
|
set_trans_object_base_flags(t);
|
|
|
|
|
|
|
|
/* count */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
2007-12-21 01:53:55 +00:00
|
|
|
if TESTBASE(base) {
|
2005-04-10 18:33:19 +00:00
|
|
|
ob= base->object;
|
|
|
|
|
|
|
|
/* store ipo keys? */
|
2007-12-21 01:53:55 +00:00
|
|
|
if (ob->id.lib == 0 && ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
elems.first= elems.last= NULL;
|
|
|
|
make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
|
|
|
|
|
|
|
|
pushdata(&elems, sizeof(ListBase));
|
|
|
|
|
2007-12-21 01:53:55 +00:00
|
|
|
for(ik= elems.first; ik; ik= ik->next)
|
|
|
|
t->total++;
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2007-12-21 01:53:55 +00:00
|
|
|
if(elems.first==NULL)
|
|
|
|
t->total++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->total++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!t->total) {
|
|
|
|
/* clear here, main transform function escapes too */
|
|
|
|
clear_trans_object_base_flags();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-05-29 22:12:12 +00:00
|
|
|
td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
|
|
|
|
tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
2007-12-21 01:53:55 +00:00
|
|
|
if TESTBASE(base) {
|
2005-04-10 18:33:19 +00:00
|
|
|
ob= base->object;
|
|
|
|
|
2007-12-21 01:53:55 +00:00
|
|
|
td->flag = TD_SELECTED;
|
2005-10-29 20:08:25 +00:00
|
|
|
td->protectflag= ob->protectflag;
|
2005-04-10 18:33:19 +00:00
|
|
|
td->ext = tx;
|
2007-12-05 11:19:36 +00:00
|
|
|
|
2007-12-21 01:53:55 +00:00
|
|
|
/* select linked objects, but skip them later */
|
|
|
|
if (ob->id.lib != 0) {
|
|
|
|
td->flag |= TD_SKIP;
|
|
|
|
}
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
/* store ipo keys? */
|
2007-12-21 01:53:55 +00:00
|
|
|
if(ob->id.lib == 0 && ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
popfirst(&elems); // bring back pushed listbase
|
|
|
|
|
|
|
|
if(elems.first) {
|
2006-05-07 08:23:51 +00:00
|
|
|
int cfraont;
|
2005-04-10 18:33:19 +00:00
|
|
|
int ipoflag;
|
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
base->flag |= BA_DO_IPO+BA_WAS_SEL;
|
2005-04-10 18:33:19 +00:00
|
|
|
base->flag &= ~SELECT;
|
|
|
|
|
|
|
|
cfraont= CFRA;
|
|
|
|
set_no_parent_ipo(1);
|
|
|
|
ipoflag= ob->ipoflag;
|
|
|
|
ob->ipoflag &= ~OB_OFFS_OB;
|
|
|
|
|
2006-12-03 18:30:34 +00:00
|
|
|
/*
|
|
|
|
* This is really EVIL code that pushes down Object values
|
|
|
|
* (loc, dloc, orig, size, dsize, rot, drot)
|
|
|
|
* */
|
|
|
|
|
|
|
|
pushdata((void*)ob->loc, 7 * 3 * sizeof(float)); // tsk! tsk!
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
for(ik= elems.first; ik; ik= ik->next) {
|
|
|
|
|
|
|
|
/* weak... this doesn't correct for floating values, giving small errors */
|
2006-05-07 08:23:51 +00:00
|
|
|
CFRA= (int)(ik->val/G.scene->r.framelen);
|
2005-04-10 18:33:19 +00:00
|
|
|
|
|
|
|
do_ob_ipo(ob);
|
2007-11-10 02:53:19 +00:00
|
|
|
ObjectToTransData(t, td, ob); // does where_is_object()
|
2005-04-10 18:33:19 +00:00
|
|
|
|
2005-05-29 23:21:56 +00:00
|
|
|
td->flag= TD_SELECTED;
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
|
|
|
|
/* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
|
|
|
|
ipokey_to_transdata(ik, td);
|
|
|
|
|
|
|
|
td++;
|
|
|
|
tx++;
|
|
|
|
if(ik->next) td->ext= tx; // prevent corrupting mem!
|
|
|
|
}
|
|
|
|
free_ipokey(&elems);
|
|
|
|
|
|
|
|
poplast(ob->loc);
|
|
|
|
set_no_parent_ipo(0);
|
|
|
|
|
2006-05-07 08:23:51 +00:00
|
|
|
CFRA= cfraont;
|
2005-04-10 18:33:19 +00:00
|
|
|
ob->ipoflag= ipoflag;
|
2005-05-29 23:21:56 +00:00
|
|
|
|
|
|
|
where_is_object(ob); // restore
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
else {
|
2007-11-10 02:53:19 +00:00
|
|
|
ObjectToTransData(t, td, ob);
|
2005-04-10 18:33:19 +00:00
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
2005-05-29 22:39:49 +00:00
|
|
|
td++;
|
|
|
|
tx++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-11-10 02:53:19 +00:00
|
|
|
ObjectToTransData(t, td, ob);
|
2005-04-10 18:33:19 +00:00
|
|
|
td->tdi = NULL;
|
|
|
|
td->val = NULL;
|
2005-05-29 22:39:49 +00:00
|
|
|
td++;
|
|
|
|
tx++;
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void createTransData(TransInfo *t)
|
|
|
|
{
|
2005-07-23 18:52:31 +00:00
|
|
|
Object *ob= OBACT;
|
|
|
|
|
2005-04-10 18:33:19 +00:00
|
|
|
if (t->context == CTX_TEXTURE) {
|
|
|
|
t->flag |= T_TEXTURE;
|
|
|
|
createTransTexspace(t);
|
|
|
|
}
|
|
|
|
else if (t->context == CTX_EDGE) {
|
|
|
|
t->ext = NULL;
|
|
|
|
t->flag |= T_EDIT;
|
|
|
|
createTransEdge(t);
|
|
|
|
if(t->data && t->flag & T_PROP_EDIT) {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 1);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
|
|
|
}
|
2008-02-23 22:46:55 +00:00
|
|
|
else if (t->context == CTX_BMESH) {
|
|
|
|
createTransBMeshVerts(t, G.editBMesh->bm, G.editBMesh->td);
|
|
|
|
}
|
2005-08-23 18:13:30 +00:00
|
|
|
else if (t->spacetype == SPACE_IMAGE) {
|
|
|
|
t->flag |= T_POINTS|T_2D_EDIT;
|
|
|
|
createTransUVs(t);
|
|
|
|
if(t->data && (t->flag & T_PROP_EDIT)) {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 1);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
else if (t->spacetype == SPACE_ACTION) {
|
|
|
|
t->flag |= T_POINTS|T_2D_EDIT;
|
|
|
|
createTransActionData(t);
|
|
|
|
}
|
|
|
|
else if (t->spacetype == SPACE_NLA) {
|
|
|
|
t->flag |= T_POINTS|T_2D_EDIT;
|
2007-09-30 11:43:16 +00:00
|
|
|
createTransNlaData(t);
|
|
|
|
}
|
|
|
|
else if (t->spacetype == SPACE_IPO) {
|
|
|
|
t->flag |= T_POINTS|T_2D_EDIT;
|
|
|
|
createTransIpoData(t);
|
|
|
|
if (t->data && (t->flag & T_PROP_EDIT)) {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 1);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
2007-09-24 11:29:25 +00:00
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
else if (G.obedit) {
|
|
|
|
t->ext = NULL;
|
|
|
|
if (G.obedit->type == OB_MESH) {
|
|
|
|
createTransEditVerts(t);
|
|
|
|
}
|
|
|
|
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
|
|
|
|
createTransCurveVerts(t);
|
|
|
|
}
|
|
|
|
else if (G.obedit->type==OB_LATTICE) {
|
|
|
|
createTransLatticeVerts(t);
|
|
|
|
}
|
|
|
|
else if (G.obedit->type==OB_MBALL) {
|
|
|
|
createTransMBallVerts(t);
|
|
|
|
}
|
|
|
|
else if (G.obedit->type==OB_ARMATURE) {
|
2005-12-19 16:45:11 +00:00
|
|
|
t->flag &= ~T_PROP_EDIT;
|
2005-04-10 18:33:19 +00:00
|
|
|
createTransArmatureVerts(t);
|
|
|
|
}
|
|
|
|
else {
|
2007-08-09 01:07:27 +00:00
|
|
|
printf("not done yet! only have mesh surface curve lattice mball armature\n");
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(t->data && t->flag & T_PROP_EDIT) {
|
|
|
|
if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 0);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 1);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
|
|
|
}
|
2005-08-23 18:13:30 +00:00
|
|
|
|
|
|
|
t->flag |= T_EDIT|T_POINTS;
|
2005-07-16 19:07:02 +00:00
|
|
|
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
/* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
|
2005-07-16 19:07:02 +00:00
|
|
|
if(t->mode==TFM_BONESIZE) {
|
2005-08-23 18:13:30 +00:00
|
|
|
t->flag &= ~(T_EDIT|T_POINTS);
|
2005-07-16 19:07:02 +00:00
|
|
|
t->flag |= T_POSE;
|
Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
keep the PoseMode hidden Bones separate from EditMode.
(In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
data. Sounds logical, but remember that VertexGroups are partial on a
Mesh, partial on Object. Weird design decision though...
Anyhoo, at this moment the only way to have Bone Envelopes deform, is
by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
set.
2005-08-19 12:35:15 +00:00
|
|
|
t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
|
2005-07-16 19:07:02 +00:00
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
2005-07-23 20:56:40 +00:00
|
|
|
else if (ob && (ob->flag & OB_POSEMODE)) {
|
2005-10-30 13:50:42 +00:00
|
|
|
createTransPose(t, OBACT);
|
2005-08-16 10:17:02 +00:00
|
|
|
}
|
|
|
|
else if (G.f & G_WEIGHTPAINT) {
|
|
|
|
/* exception, we look for the one selected armature */
|
|
|
|
Base *base;
|
|
|
|
for(base=FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(base)) {
|
|
|
|
if(base->object->type==OB_ARMATURE)
|
|
|
|
if(base->object->flag & OB_POSEMODE)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(base) {
|
2005-10-30 13:50:42 +00:00
|
|
|
createTransPose(t, base->object);
|
2005-08-16 10:17:02 +00:00
|
|
|
}
|
2005-07-23 20:56:40 +00:00
|
|
|
}
|
2007-12-04 13:57:28 +00:00
|
|
|
else if (G.f & G_PARTICLEEDIT && PE_can_edit(PE_get_current(ob))) {
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
createTransParticleVerts(t);
|
|
|
|
|
|
|
|
if(t->data && t->flag & T_PROP_EDIT) {
|
|
|
|
sort_trans_data(t); // makes selected become first in array
|
|
|
|
set_prop_dist(t, 1);
|
|
|
|
sort_trans_data_dist(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->flag |= T_POINTS;
|
|
|
|
}
|
2005-04-10 18:33:19 +00:00
|
|
|
else {
|
|
|
|
createTransObject(t);
|
|
|
|
t->flag |= T_OBJECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
|
|
|
|
t->flag |= T_CAMERA;
|
|
|
|
}
|
Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
(pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
system should be built from scratch. I can't really understand this code...
I expect it is not much needed, especially with advanced layer/passes
control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
to check first the option to render to a Image window, so Blender can become
a true single-window application. :)
For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
2006-01-23 22:05:47 +00:00
|
|
|
|
|
|
|
/* temporal...? */
|
|
|
|
G.scene->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
|
2005-04-10 18:33:19 +00:00
|
|
|
}
|
|
|
|
|
2007-11-08 08:27:21 +00:00
|
|
|
|
2007-12-15 07:35:16 +00:00
|
|
|
|