svn merge -r 13148:13177 https://svn.blender.org/svnroot/bf-blender/trunk/blender + fixed one crash on enabling deflection

This commit is contained in:
Daniel Genrich
2008-01-09 12:04:54 +00:00
24 changed files with 1282 additions and 256 deletions

View File

@@ -41,6 +41,7 @@ typedef struct BodyPoint {
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
float goal;
float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
float impdv[3],impdx[3];
int nofsprings; int *springs;
float choke;
float colball;

View File

@@ -9,6 +9,7 @@ incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/bmfont'
incs += ' #/intern/opennl/extern'
incs += ' ' + env['BF_OPENGL_INC']
incs += ' ' + env['BF_ZLIB_INC']

View File

@@ -47,6 +47,7 @@
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
@@ -76,7 +77,7 @@
#define MAX_DUPLI_RECUR 4
static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level);
static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level);
void free_path(Path *path)
{
@@ -327,7 +328,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level)
if(go->ob->transflag & OB_DUPLI) {
Mat4CpyMat4(dob->ob->obmat, dob->mat);
object_duplilist_recursive((ID *)group, go->ob, lb, &ob->obmat, level+1);
object_duplilist_recursive((ID *)group, go->ob, lb, ob->obmat, level+1);
Mat4CpyMat4(dob->ob->obmat, dob->omat);
}
}
@@ -412,12 +413,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
float tmpmat[4][4];
Mat4CpyMat4(tmpmat, vdd->ob->obmat);
Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, &obmat, vdd->level+1);
object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, obmat, vdd->level+1);
Mat4CpyMat4(vdd->ob->obmat, tmpmat);
}
}
static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level)
{
Object *ob, *ob_iter;
Base *base = NULL;
@@ -473,11 +474,11 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac
/* par_space_mat - only used for groups so we can modify the space dupli's are in
when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
*/
if (par_space_mat) {
Mat4MulMat4(vdd.obmat, ob->obmat, *par_space_mat);
} else {
if(par_space_mat)
Mat4MulMat4(vdd.obmat, ob->obmat, par_space_mat);
else
Mat4CpyMat4(vdd.obmat, ob->obmat);
}
vdd.id= id;
vdd.level= level;
vdd.lb= lb;
@@ -512,7 +513,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac
dm->release(dm);
}
static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level)
{
Object *ob, *ob_iter;
Base *base = NULL;
@@ -583,11 +584,10 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
/* par_space_mat - only used for groups so we can modify the space dupli's are in
when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
*/
if (par_space_mat) {
Mat4MulMat4(ob__obmat, ob->obmat, *par_space_mat);
} else {
if(par_space_mat)
Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat);
else
Mat4CpyMat4(ob__obmat, ob->obmat);
}
Mat3CpyMat4(imat, ob->parentinv);
@@ -638,7 +638,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
float tmpmat[4][4];
Mat4CpyMat4(tmpmat, ob->obmat);
Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
object_duplilist_recursive((ID *)id, ob, lb, &ob->obmat, level+1);
object_duplilist_recursive((ID *)id, ob, lb, ob->obmat, level+1);
Mat4CpyMat4(ob->obmat, tmpmat);
}
}
@@ -660,17 +660,46 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
dm->release(dm);
}
static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSystem *psys, int level)
static void particle_dupli_path_rotation(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
{
float loc[3], nor[3], vec[3], side[3], len;
VecSubf(vec, (cache+cache->steps-1)->co, cache->co);
len= Normalize(vec);
if(pa)
psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
else
psys_particle_on_emitter(ob, psmd,
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
Crossf(side, nor, vec);
Normalize(side);
Crossf(nor, vec, side);
Mat4One(mat);
VECCOPY(mat[0], vec);
VECCOPY(mat[1], side);
VECCOPY(mat[2], nor);
*scale= len;
}
static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level)
{
GroupObject *go;
Object *ob, **oblist=0;
Object *ob=0, **oblist=0;
ParticleSettings *part;
ParticleData *pa;
ParticleKey state;
float ctime, pa_time;
float tmat[4][4], mat[3][3], obrotmat[3][3], parotmat[3][3], size=0.0;
ParticleCacheKey *cache;
ParticleSystemModifierData *psmd;
float ctime, pa_time, scale = 1.0f;
float tmat[4][4], mat[4][4], obrotmat[4][4], pamat[4][4], size=0.0;
float obmat[4][4], (*obmatlist)[4][4]=0;
float xvec[3] = {-1.0, 0.0, 0.0}, *q;
int lay, a, k, step_nbr = 0, counter;
int lay, a, b, k, step_nbr = 0, counter, hair = 0;
int totpart, totchild, totgroup=0, pa_num;
if(psys==0) return;
@@ -678,9 +707,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
if (GS(id->name)!=ID_SCE) return; /* No support for groups YET! TODO */
part=psys->part;
psmd= psys_get_modifier(par, psys);
if(part==0) return;
@@ -700,6 +728,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
else
step_nbr = 0;
if(psys->flag & PSYS_HAIR_DONE)
hair= (totchild == 0 || psys->childcache) && psys->pathcache;
psys->lattice = psys_get_lattice(par, psys);
if(part->draw_as==PART_DRAW_GR) {
@@ -712,9 +743,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
}
oblist= MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
obmatlist= MEM_callocN(totgroup*sizeof(float)*4*4, "dupgroup obmat list");
go= part->dup_group->gobject.first;
for(a=0; a<totgroup; a++, go=go->next)
for(a=0; a<totgroup; a++, go=go->next) {
oblist[a]=go->ob;
Mat4CpyMat4(obmatlist[a], go->ob->obmat);
}
}
else {
ob = part->dup_ob;
Mat4CpyMat4(obmat, ob->obmat);
}
if(totchild==0 || part->draw & PART_DRAW_PARENT)
@@ -724,7 +762,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) {
if(a<totpart) {
if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP))
continue;
pa_num=pa->num;
@@ -742,61 +781,91 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
if(part->draw_as==PART_DRAW_GR) {
if(part->draw&PART_DRAW_RAND_GR)
ob = oblist[BLI_rand() % totgroup];
b= BLI_rand() % totgroup;
else if(part->from==PART_FROM_PARTICLE)
ob = oblist[pa_num % totgroup];
b= pa_num % totgroup;
else
ob = oblist[a % totgroup];
b= a % totgroup;
ob = oblist[b];
Mat4CpyMat4(obmat, obmatlist[b]);
}
else
ob = part->dup_ob;
for(k=0; k<=step_nbr; k++, counter++) {
if(step_nbr) {
if(hair) {
if(a < totpart) {
cache = psys->pathcache[a];
particle_dupli_path_rotation(par, part, psmd, pa, 0, cache, pamat, &scale);
}
else {
ChildParticle *cpa= psys->child+(a-totpart);
cache = psys->childcache[a-totpart];
particle_dupli_path_rotation(par, part, psmd, 0, cpa, cache, pamat, &scale);
}
VECCOPY(pamat[3], cache->co);
}
else if(step_nbr) {
state.time = (float)k / (float)step_nbr;
psys_get_particle_on_path(par, psys, a, &state, 0);
QuatToMat4(state.rot, pamat);
VECCOPY(pamat[3], state.co);
pamat[3][3]= 1.0f;
}
else {
state.time = -1.0;
if(psys_get_particle_state(par, psys, a, &state, 0) == 0)
continue;
QuatToMat4(state.rot, pamat);
VECCOPY(pamat[3], state.co);
pamat[3][3]= 1.0f;
}
QuatToMat3(state.rot, parotmat);
if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
for(go= part->dup_group->gobject.first; go; go= go->next) {
for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {
Mat4CpyMat4(tmat, go->ob->obmat);
Mat4MulMat43(tmat, go->ob->obmat, parotmat);
Mat4MulFloat3((float *)tmat, size);
Mat4MulMat4(tmat, obmatlist[b], pamat);
Mat4MulFloat3((float *)tmat, size*scale);
if(par_space_mat)
Mat4MulMat4(mat, tmat, par_space_mat);
else
Mat4CpyMat4(mat, tmat);
VECADD(tmat[3], go->ob->obmat[3], state.co);
new_dupli_object(lb, go->ob, tmat, par->lay, counter, OB_DUPLIPARTS);
new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS);
}
}
else {
/* to give ipos in object correct offset */
where_is_object_time(ob, ctime-pa_time);
q = vectoquat(xvec, ob->trackflag, ob->upflag);
QuatToMat3(q, obrotmat);
if(!hair) {
q = vectoquat(xvec, ob->trackflag, ob->upflag);
QuatToMat4(q, obrotmat);
obrotmat[3][3]= 1.0f;
Mat3MulMat3(mat, parotmat, obrotmat);
Mat4CpyMat4(tmat, ob->obmat);
Mat4MulMat43(tmat, ob->obmat, mat);
Mat4MulFloat3((float *)tmat, size);
Mat4MulMat4(mat, obrotmat, pamat);
}
else
Mat4CpyMat4(mat, pamat);
VECCOPY(tmat[3], state.co);
Mat4MulMat4(tmat, obmat, mat);
Mat4MulFloat3((float *)tmat, size*scale);
if(par_space_mat)
Mat4MulMat4(mat, tmat, par_space_mat);
else
Mat4CpyMat4(mat, tmat);
new_dupli_object(lb, ob, tmat, par->lay, counter, OB_DUPLIPARTS);
new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS);
}
}
}
}
if(oblist)
MEM_freeN(oblist);
if(obmatlist)
MEM_freeN(obmatlist);
if(psys->lattice) {
end_latt_deform();
@@ -877,7 +946,7 @@ static void font_duplilist(ListBase *lb, Object *par, int level)
}
/* ***************************** */
static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level)
static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level)
{
if((ob->transflag & OB_DUPLI)==0)
return;
@@ -896,7 +965,7 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist,
if(ob->transflag & OB_DUPLIPARTS) {
ParticleSystem *psys = ob->particlesystem.first;
for(; psys; psys=psys->next)
new_particle_duplilist(duplilist, id, ob, psys, level+1);
new_particle_duplilist(duplilist, id, ob, par_space_mat, psys, level+1);
}
else if(ob->transflag & OB_DUPLIVERTS) {
if(ob->type==OB_MESH) {

View File

@@ -1533,10 +1533,10 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
ParticleTexture ptex;
ParticleKey state;
IpoCurve *icu=0;
float fac, rotfac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
float q_one[4]={1.0,0.0,0.0,0.0}, q_phase[4];
float q_phase[4];
part=psys->part;
ptex.ivel=1.0;
@@ -4241,7 +4241,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
}
if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && (psys_in_edit_mode(psys)
|| part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){
|| (part->type==PART_HAIR || part->draw_as==PART_DRAW_PATH) || part->draw&PART_DRAW_KEYS)){
psys_cache_paths(ob, psys, cfra, 0);
/* for render, child particle paths are computed on the fly */

View File

@@ -87,6 +87,7 @@ variables on the UI for now
#include "BIF_editdeform.h"
#include "BIF_graphics.h"
#include "PIL_time.h"
#include "ONL_opennl.h"
/* callbacks for errors and interrupts and some goo */
static int (*SB_localInterruptCallBack)(void) = NULL;
@@ -97,7 +98,7 @@ static int (*SB_localInterruptCallBack)(void) = NULL;
typedef struct BodySpring {
int v1, v2;
float len, strength, cf;
float len, strength, cf,load;
float ext_force[3]; /* edges colliding and sailing */
short order;
short flag;
@@ -120,6 +121,11 @@ typedef struct SBScratch {
float aabbmin[3],aabbmax[3];
}SBScratch;
#define NLF_BUILD 1
#define NLF_SOLVE 2
#define MID_PRESERVE 1
#define SOFTGOALSNAP 0.999f
/* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
removes *unnecessary* stiffnes from ODE system
@@ -585,6 +591,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
if (ob->soft){
int nofquads;
float s_shear = ob->soft->shearstiff*ob->soft->shearstiff;
nofquads = count_mesh_quads(me);
if (nofquads) {
@@ -605,12 +612,12 @@ static void add_mesh_quad_diag_springs(Object *ob)
if(mface->v4) {
bs->v1= mface->v1;
bs->v2= mface->v3;
bs->strength= 1.0;
bs->strength= s_shear;
bs->order =2;
bs++;
bs->v1= mface->v2;
bs->v2= mface->v4;
bs->strength= 1.0;
bs->strength= s_shear;
bs->order =2;
bs++;
@@ -692,6 +699,7 @@ static void add_2nd_order_springs(Object *ob,float stiffness)
{
int counter = 0;
BodySpring *bs_new;
stiffness *=stiffness;
add_2nd_order_roller(ob,stiffness,&counter,0); /* counting */
if (counter) {
@@ -1450,6 +1458,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
}
void scan_for_ext_spring_forces(Object *ob,float timenow)
{
SoftBody *sb = ob->soft;
@@ -2095,8 +2104,110 @@ static int sb_deflect_face(Object *ob,float *actpos,float *facenormal,float *for
return(deflected);
}
static void dfdx_spring(int ia, int ic, int op, float dir[3],float L,float len,float factor)
{
float m,delta_ij;
int i ,j;
if (L < len){
for(i=0;i<3;i++)
for(j=0;j<3;j++){
delta_ij = (i==j ? (1.0f): (0.0f));
m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
nlMatrixAdd(ia+i,op+ic+j,m);
}
}
else{
for(i=0;i<3;i++)
for(j=0;j<3;j++){
m=factor*dir[i]*dir[j];
nlMatrixAdd(ia+i,op+ic+j,m);
}
}
}
static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
static void dfdx_goal(int ia, int ic, int op, float factor)
{
int i;
for(i=0;i<3;i++) nlMatrixAdd(ia+i,op+ic+i,factor);
}
static void dfdv_goal(int ia, int ic,float factor)
{
int i;
for(i=0;i<3;i++) nlMatrixAdd(ia+i,ic+i,factor);
}
static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
{
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp1,*bp2;
float dir[3],dvel[3];
float distance,forcefactor,kd,absvel,projvel;
int ia,ic;
/* prepare depending on which side of the spring we are on */
if (bpi == bs->v1){
bp1 = &sb->bpoint[bs->v1];
bp2 = &sb->bpoint[bs->v2];
ia =3*bs->v1;
ic =3*bs->v2;
}
else if (bpi == bs->v2){
bp1 = &sb->bpoint[bs->v2];
bp2 = &sb->bpoint[bs->v1];
ia =3*bs->v2;
ic =3*bs->v1;
}
else{
/* TODO make this debug option */
/**/
printf("bodypoint <bpi> is not attached to spring <*bs> --> sb_spring_force()\n");
return;
}
/* do bp1 <--> bp2 elastic */
VecSubf(dir,bp1->pos,bp2->pos);
distance = Normalize(dir);
if (bs->len < distance)
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
else
iks = 1.0f/(1.0f-sb->inpush)-1.0f ;/* inner spring constants function */
if(bs->len > 0.0f) /* check for degenerated springs */
forcefactor = iks/bs->len;
else
forcefactor = iks;
forcefactor *= bs->strength;
Vec3PlusStVec(bp1->force,(bs->len - distance)*forcefactor,dir);
/* do bp1 <--> bp2 viscous */
VecSubf(dvel,bp1->vec,bp2->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalize(dvel);
projvel = Inpf(dir,dvel);
kd *= absvel * projvel;
Vec3PlusStVec(bp1->force,-kd,dir);
/* do jacobian stuff if needed */
if(nl_flags & NLF_BUILD){
int op =3*sb->totpoint;
float mvel = -forcetime*kd;
float mpos = -forcetime*forcefactor;
/* depending on my pos */
dfdx_spring(ia,ia,op,dir,bs->len,distance,-mpos);
/* depending on my vel */
dfdv_goal(ia,ia,mvel); // well that ignores geometie
if(bp2->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */
/* depending on other pos */
dfdx_spring(ia,ic,op,dir,bs->len,distance,mpos);
/* depending on other vel */
dfdv_goal(ia,ia,-mvel); // well that ignores geometie
}
}
}
static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags)
{
/* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM)
@@ -2106,10 +2217,20 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
BodyPoint *bproot;
BodySpring *bs;
ListBase *do_effector;
float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3];
float iks, ks, kd, gravity;
float fieldfactor = 1000.0f, windfactor = 250.0f;
float tune = sb->ballstiff;
int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero;
NLboolean success;
if(nl_flags){
nlBegin(NL_SYSTEM);
nlBegin(NL_MATRIX);
}
gravity = sb->grav * sb_grav_force_scale(ob);
@@ -2131,7 +2252,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
float defforce[3];
do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
}
/*
if (do_selfcollision ){
float ce[3];
VecMidf(ce,sb->scratch->aabbmax,sb->scratch->aabbmin);
@@ -2139,10 +2260,33 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
bp->octantflag = set_octant_flags(ce,bp->pos,bp->colball);
}
}
*/
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
/* clear forces accumulator */
bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
if(nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
int op =3*sb->totpoint;
/* dF/dV = v */
nlMatrixAdd(op+ia,ia,-forcetime);
nlMatrixAdd(op+ia+1,ia+1,-forcetime);
nlMatrixAdd(op+ia+2,ia+2,-forcetime);
/* we need [unit - h* dF/dy]^-1 */
nlMatrixAdd(ia,ia,1);
nlMatrixAdd(ia+1,ia+1,1);
nlMatrixAdd(ia+2,ia+2,1);
nlMatrixAdd(op+ia,op+ia,1);
nlMatrixAdd(op+ia+1,op+ia+1,1);
nlMatrixAdd(op+ia+2,op+ia+2,1);
}
/* naive ball self collision */
/* needs to be done if goal snaps or not */
@@ -2156,7 +2300,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) {
if ((bp->octantflag & obp->octantflag) == 0) continue;
//if ((bp->octantflag & obp->octantflag) == 0) continue;
compare = (obp->colball + bp->colball);
VecSubf(def, bp->pos, obp->pos);
@@ -2182,8 +2326,33 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
VecSubf(dvel,velcenter,bp->vec);
VecMulf(dvel,sb->nodemass);
Vec3PlusStVec(bp->force,sb->balldamp,dvel);
Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
Vec3PlusStVec(bp->force,sb->balldamp,dvel);
if(nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
int ic =3*(sb->totpoint-c);
int op =3*sb->totpoint;
float mvel = forcetime*sb->nodemass*sb->balldamp;
float mpos = forcetime*tune*(1.0f-sb->balldamp);
/*some quick and dirty entries to the jacobian*/
dfdx_goal(ia,ia,op,mpos);
dfdv_goal(ia,ia,mvel);
/* exploit force(a,b) == -force(b,a) part1/2 */
dfdx_goal(ic,ic,op,mpos);
dfdv_goal(ic,ic,mvel);
/*TODO sit down an X-out the true jacobian entries*/
/*well does not make to much sense because the eigenvalues
of the jacobian go negative; and negative eigenvalues
on a complex iterative system z(n+1)=A * z(n)
give imaginary roots in the charcateristic polynom
--> solutions that to z(t)=u(t)* exp ( i omega t) --> oscilations we don't want here
where u(t) is a unknown amplitude function (worst case rising fast)
*/
}
/* exploit force(a,b) == -force(b,a) part2/2 */
VecSubf(dvel,velcenter,obp->vec);
VecMulf(dvel,sb->nodemass);
@@ -2191,6 +2360,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
Vec3PlusStVec(obp->force,sb->balldamp,dvel);
Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
}
}
}
@@ -2201,23 +2371,39 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
float auxvect[3];
float velgoal[3];
float absvel =0, projvel= 0;
/* do goal stuff */
if(ob->softflag & OB_SB_GOAL) {
/* true elastic goal */
VecSubf(auxvect,bp->origT,bp->pos);
VecSubf(auxvect,bp->pos,bp->origT);
ks = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ;
bp->force[0]+= ks*(auxvect[0]);
bp->force[1]+= ks*(auxvect[1]);
bp->force[2]+= ks*(auxvect[2]);
bp->force[0]+= -ks*(auxvect[0]);
bp->force[1]+= -ks*(auxvect[1]);
bp->force[2]+= -ks*(auxvect[2]);
if(nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
int op =3*(sb->totpoint);
/* depending on my pos */
dfdx_goal(ia,ia,op,ks*forcetime);
}
/* calulate damping forces generated by goals*/
VecSubf(velgoal,bp->origS, bp->origE);
kd = sb->goalfrict * sb_fric_force_scale(ob) ;
VecAddf(auxvect,velgoal,bp->vec);
if (forcetime > 0.0 ) { /* make sure friction does not become rocket motor on time reversal */
bp->force[0]-= kd * (velgoal[0] + bp->vec[0]);
bp->force[1]-= kd * (velgoal[1] + bp->vec[1]);
bp->force[2]-= kd * (velgoal[2] + bp->vec[2]);
bp->force[0]-= kd * (auxvect[0]);
bp->force[1]-= kd * (auxvect[1]);
bp->force[2]-= kd * (auxvect[2]);
if(nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
Normalize(auxvect);
/* depending on my vel */
dfdv_goal(ia,ia,kd*forcetime);
}
}
else {
bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
@@ -2230,6 +2416,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
/* gravitation */
bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
//bp->force[1]-= gravity*sb->nodemass; /* individual mass of node here */
/* particle field & vortex */
@@ -2260,6 +2447,16 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
bp->force[1]-= bp->vec[1]*kd;
bp->force[2]-= bp->vec[2]*kd;
/* friction in media done */
if(nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
int op =3*sb->totpoint;
/* da/dv = */
nlMatrixAdd(ia,ia,forcetime*kd);
nlMatrixAdd(ia+1,ia+1,forcetime*kd);
nlMatrixAdd(ia+2,ia+2,forcetime*kd);
}
}
/* +++cached collision targets */
bp->choke = 0.0f;
@@ -2269,7 +2466,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
kd = 1.0f;
if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
if (intrusion < 0.0f){
if ((!nl_flags)&&(intrusion < 0.0f)){
/*bjornmose: uugh.. what an evil hack
violation of the 'don't touch bp->pos in here' rule
but works nice, like this-->
@@ -2287,8 +2484,15 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
VECSUB(cfforce,bp->vec,vel);
Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
}
Vec3PlusStVec(bp->force,kd,defforce);
if (nl_flags & NLF_BUILD){
int ia =3*(sb->totpoint-a);
int op =3*sb->totpoint;
//dfdx_goal(ia,ia,op,mpos); // don't do unless you know
//dfdv_goal(ia,ia,-cf);
}
}
}
@@ -2305,48 +2509,8 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
bp->choke = bs->cf;
}
if (( (sb->totpoint-a) == bs->v1) ){
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
actspringlen=Normalize(sd);
/* friction stuff V1 */
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalize(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0f) /* check for degenerated springs */
forcefactor = (bs->len - actspringlen)/bs->len * iks;
else
forcefactor = actspringlen * iks;
forcefactor *= bs->strength;
Vec3PlusStVec(bp->force,-forcefactor,sd);
}
if (( (sb->totpoint-a) == bs->v2) ){
VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
actspringlen=Normalize(sd);
/* friction stuff V2 */
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalize(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0)
forcefactor = (bs->len - actspringlen)/bs->len * iks;
else
forcefactor = actspringlen * iks;
forcefactor *= bs->strength;
Vec3PlusStVec(bp->force,+forcefactor,sd);
}
// sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
sb_spring_force(ob,sb->totpoint-a,bs,iks,forcetime,nl_flags);
}/* loop springs */
}/* existing spring list */
}/*any edges*/
@@ -2356,14 +2520,206 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
/* finally add forces caused by face collision */
if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
/* finish matrix and solve */
if(nl_flags & NLF_SOLVE){
//double sct,sst=PIL_check_seconds_timer();
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
int iv =3*(sb->totpoint-a);
int ip =3*(2*sb->totpoint-a);
int n;
for (n=0;n<3;n++) {nlRightHandSideSet(0, iv+n, bp->force[0+n]);}
for (n=0;n<3;n++) {nlRightHandSideSet(0, ip+n, bp->vec[0+n]);}
}
nlEnd(NL_MATRIX);
nlEnd(NL_SYSTEM);
if ((G.rt >0) && (nl_flags & NLF_BUILD))
{
printf("####MEE#####\n");
nlPrintMatrix();
}
success= nlSolveAdvanced(NULL, 1);
// nlPrintMatrix(); /* for debug purpose .. anyhow cropping B vector looks like working */
if(success){
float f;
int index =0;
/* for debug purpose .. anyhow cropping B vector looks like working */
if (G.rt >0)
for(a=2*sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
f=nlGetVariable(0,index);
printf("(%f ",f);index++;
f=nlGetVariable(0,index);
printf("%f ",f);index++;
f=nlGetVariable(0,index);
printf("%f)",f);index++;
}
index =0;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
f=nlGetVariable(0,index);
bp->impdv[0] = f; index++;
f=nlGetVariable(0,index);
bp->impdv[1] = f; index++;
f=nlGetVariable(0,index);
bp->impdv[2] = f; index++;
}
/*
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
f=nlGetVariable(0,index);
bp->impdx[0] = f; index++;
f=nlGetVariable(0,index);
bp->impdx[1] = f; index++;
f=nlGetVariable(0,index);
bp->impdx[2] = f; index++;
}
*/
}
else{
printf("Matrix inversion failed \n");
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
VECCOPY(bp->impdv,bp->force);
}
}
//sct=PIL_check_seconds_timer();
//if (sct-sst > 0.01f) printf(" implicit solver time %f %s \r",sct-sst,ob->id.name);
}
/* cleanup */
if(do_effector) pdEndEffectors(do_effector);
}
static void softbody_apply_fake_implicit_forces(Object *ob, float forcetime, float *err, float *err_ref_pos,float *err_ref_vel)
{
/* time evolution */
/* do semi implicit euler */
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp;
float *perp,*perv;
float erp[3],erv[3],dx[3],dv[3],aabbmin[3],aabbmax[3],cm[3]={0.0f,0.0f,0.0f};
float timeovermass;
float maxerrpos= 0.0f,maxerrvel = 0.0f,maxerrvel2 = 0.0f;
int a,fuzzy=0;
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
forcetime *= sb_time_scale(ob);
aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f;
aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f;
/* claim a minimum mass for vertex */
if (sb->nodemass > 0.009999f) timeovermass = forcetime/sb->nodemass;
else timeovermass = forcetime/0.009999f;
/* step along error reference vector */
perp =err_ref_pos;
perv =err_ref_vel;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
/* step along error reference vector */
if(perp) {VECCOPY(erp,perp);perp +=3;}
if(perv) {VECCOPY(erv,perv);perv +=3;}
if(bp->goal < SOFTGOALSNAP){
/* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/
/* the ( ... )' operator denotes derivate respective time */
/* the "implicit" euler step for velocity then becomes */
/* v(t + dt) = v(t) + O * X(t) * dt */
/* O = [1-dt*dA/d(X)]^1 */
/* with X = (a[n],v[n]) */
/* da/dv | da/dx */
/* dA/d(X) = ( ------------- )*/
/* dv/dv | dv/dx */
/* note!! we did not solve any implicit system but looking forward more or less smart
what a implicit solution may look like by means of taylor expansion */
VECCOPY(dx,bp->vec);
bp->force[0]= timeovermass * bp->impdv[0]; /* individual mass of node here */
bp->force[1]= timeovermass * bp->impdv[1];
bp->force[2]= timeovermass * bp->impdv[2];
VECCOPY(dv,bp->force);
if(perv){
maxerrvel = MAX2(maxerrvel,ABS(dv[0] - erv[0]));
maxerrvel = MAX2(maxerrvel,ABS(dv[1] - erv[1]));
maxerrvel = MAX2(maxerrvel,ABS(dv[2] - erv[2]));
}
maxerrvel2 = MAX2(maxerrvel2,ABS(dv[0]));
maxerrvel2 = MAX2(maxerrvel2,ABS(dv[1]));
maxerrvel2 = MAX2(maxerrvel2,ABS(dv[2]));
VECADD(bp->vec, bp->vec, dv);
/* so here is (x)'= v(elocity) */
/* the euler step for location then becomes */
/* x(t + dt) = x(t) + v(t) * dt */
// VECCOPY(dx,bp->vec);
dx[0]*=forcetime;
dx[1]*=forcetime;
dx[2]*=forcetime;
/* bp->choke is set when we need to pull a vertex or edge out of the collider.
the collider object signals to get out by pushing hard. on the other hand
we don't want to end up in deep space so we add some <viscosity>
to balance that out */
if (bp->choke > 0.0f){
dx[0]*=(1.0f - bp->choke);
dx[1]*=(1.0f - bp->choke);
dx[2]*=(1.0f - bp->choke);
}
/* should be possible to get more out of the matrix inversion
but not verified yet
dx[0]*=forcetime*forcetime*bp->impdx[0];
dx[1]*=forcetime*forcetime*bp->impdx[1];
dx[2]*=forcetime*forcetime*bp->impdx[2];
*/
VECADD(bp->pos, bp->pos, dx);
if (perp){
maxerrpos = MAX2(maxerrpos,ABS(bp->pos[0]-erp[0]));
maxerrpos = MAX2(maxerrpos,ABS(bp->pos[1]-erp[1]));
maxerrpos = MAX2(maxerrpos,ABS(bp->pos[2]-erp[2]));
}
}/*snap*/
/* so while we are looping BPs anyway do statistics on the fly */
aabbmin[0] = MIN2(aabbmin[0],bp->pos[0]);
aabbmin[1] = MIN2(aabbmin[1],bp->pos[1]);
aabbmin[2] = MIN2(aabbmin[2],bp->pos[2]);
aabbmax[0] = MAX2(aabbmax[0],bp->pos[0]);
aabbmax[1] = MAX2(aabbmax[1],bp->pos[1]);
aabbmax[2] = MAX2(aabbmax[2],bp->pos[2]);
if (bp->flag & SBF_DOFUZZY) fuzzy =1;
} /*for*/
if (sb->totpoint) VecMulf(cm,1.0f/sb->totpoint);
if (sb->scratch){
VECCOPY(sb->scratch->aabbmin,aabbmin);
VECCOPY(sb->scratch->aabbmax,aabbmax);
}
if (err){ /* so step size will be controlled by biggest difference in slope */
if (sb->solverflags & SBSO_OLDERR)
*err = MAX2(maxerrpos,maxerrvel);
else
if (perp) *err = maxerrpos;
else *err = maxerrvel2;
//printf("EP %f EV %f \n",maxerrpos,maxerrvel);
if (fuzzy){
*err /= sb->fuzzyness;
}
}
}
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
{
/* time evolution */
/* actually does an explicit euler step mode == 0 */
@@ -2386,6 +2742,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
if(bp->goal < SOFTGOALSNAP){
if(mid_flags & MID_PRESERVE) VECCOPY(dx,bp->vec);
/* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/
/* the ( ... )' operator denotes derivate respective time */
@@ -2417,8 +2774,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
/* so here is (x)'= v(elocity) */
/* the euler step for location then becomes */
/* x(t + dt) = x(t) + v(t) * dt */
VECCOPY(dx,bp->vec);
if(!(mid_flags & MID_PRESERVE)) VECCOPY(dx,bp->vec);
dx[0]*=forcetime;
dx[1]*=forcetime;
dx[2]*=forcetime;
@@ -2490,6 +2846,79 @@ static void softbody_restore_prev_step(Object *ob)
}
}
static void softbody_store_step(Object *ob)
{
SoftBody *sb= ob->soft; /* is supposed to be there*/
BodyPoint *bp;
int a;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
VECCOPY(bp->prevvec,bp->vec);
VECCOPY(bp->prevpos,bp->pos);
}
}
/* used by predictors and correctors */
static void softbody_store_state(Object *ob,float *ppos,float *pvel)
{
SoftBody *sb= ob->soft; /* is supposed to be there*/
BodyPoint *bp;
int a;
float *pp=ppos,*pv=pvel;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
VECCOPY(pv, bp->vec);
pv+=3;
VECCOPY(pp, bp->pos);
pp+=3;
}
}
/* used by predictors and correctors */
static void softbody_retrieve_state(Object *ob,float *ppos,float *pvel)
{
SoftBody *sb= ob->soft; /* is supposed to be there*/
BodyPoint *bp;
int a;
float *pp=ppos,*pv=pvel;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
VECCOPY(bp->vec,pv);
pv+=3;
VECCOPY(bp->pos,pp);
pp+=3;
}
}
/* used by predictors and correctors */
static void softbody_swap_state(Object *ob,float *ppos,float *pvel)
{
SoftBody *sb= ob->soft; /* is supposed to be there*/
BodyPoint *bp;
int a;
float *pp=ppos,*pv=pvel;
float temp[3];
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
VECCOPY(temp, bp->vec);
VECCOPY(bp->vec,pv);
VECCOPY(pv,temp);
pv+=3;
VECCOPY(temp, bp->pos);
VECCOPY(bp->pos,pp);
VECCOPY(pp,temp);
pp+=3;
}
}
/* care for bodypoints taken out of the 'ordinary' solver step
** because they are screwed to goal by bolts
** they just need to move along with the goal in time
@@ -3193,6 +3622,8 @@ SoftBody *sbNew(void)
sb->inspring= 0.5f;
sb->infrict= 0.5f;
/*todo backward file compat should copy infrict to inpush while reading old files*/
sb->inpush = 0.5f;
sb->interval= 10;
sb->sfra= G.scene->r.sfra;
@@ -3205,9 +3636,13 @@ SoftBody *sbNew(void)
sb->minloops = 10;
sb->maxloops = 300;
sb->choke = 3;
sb_new_scratch(sb);
/*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/
sb->shearstiff = 1.0f;
sb->solverflags |= SBSO_OLDERR;
return sb;
}
@@ -3256,7 +3691,7 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
HairKey *key= NULL;
BodyPoint *bp;
int a;
float dtime,ctime,forcetime,err;
float dtime,ctime,forcetime;
float hairmat[4][4];
/* This part only sets goals and springs, based on original mesh/curve/lattice data.
@@ -3446,8 +3881,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
}
if (TRUE) { /* */
if (sb->solver_ID < 2) {
/* special case of 2nd order Runge-Kutta type AKA Heun */
int mid_flags=0;
float err = 0;
float forcetimemax = 1.0f;
float forcetimemin = 0.001f;
float timedone =0.0; /* how far did we get without violating error condition */
@@ -3459,7 +3896,8 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops;
if(sb->solver_ID>0) mid_flags |= MID_PRESERVE;
//forcetime = dtime; /* hope for integrating in one step */
forcetime =forcetimemax; /* hope for integrating in one step */
@@ -3470,13 +3908,13 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
sb->scratch->flag &= ~SBF_DOFUZZY;
/* do predictive euler step */
softbody_calc_forces(ob, forcetime,timedone/dtime);
softbody_apply_forces(ob, forcetime, 1, NULL);
softbody_calc_forces(ob, forcetime,timedone/dtime,0);
softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags);
/* crop new slope values to do averaged slope step */
softbody_calc_forces(ob, forcetime,timedone/dtime);
softbody_apply_forces(ob, forcetime, 2, &err);
softbody_calc_forces(ob, forcetime,timedone/dtime,0);
softbody_apply_forces(ob, forcetime, 2, &err,mid_flags);
softbody_apply_goalsnap(ob);
@@ -3517,6 +3955,7 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
sct=PIL_check_seconds_timer();
if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone);
}
/* ask for user break */
if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
}
@@ -3531,11 +3970,263 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
}
}
else if (sb->solver_ID == 2)
{
/* do semi "fake" implicit euler */
float *predict_vel=NULL,*predict_pos=NULL; /* for BDF style stepping */
NLContext *sb_nlc = NULL;
int npredict=0,predict_mem_size;
int nvar = 3*2*sb->totpoint;
int loops =0 ;
float forcetimemax = 1.0f; // this one needs 5 steps as a minimum
float forcetimemin = 0.001f;
float timedone =0.0; /* how far did we get without violating error condition */
/* loops = counter for emergency brake
* we don't want to lock up the system if physics fail
*/
SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops;
forcetime =forcetimemax; /* hope for integrating as fast as possible */
//allocate predictor buffers
npredict =1;
predict_mem_size =3*sizeof(float)*npredict*sb->totpoint;
predict_pos = MEM_mallocN(predict_mem_size,"SB_predict_pos");
predict_vel = MEM_mallocN(predict_mem_size,"SB_predict_vel");
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){
float loss_of_accuracy=0;
// create new solver context for this loop
sb_nlc = (NLContext*)nlNewContext();
/* hum it smells like threading trouble */
nlSolverParameteri(NL_NB_VARIABLES, nvar);
nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE);
interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
softbody_store_step(ob); /* used for rolling back step guessing */
softbody_store_state(ob,predict_pos,predict_vel);
softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE);
// go full step
softbody_apply_fake_implicit_forces(ob, forcetime, NULL,NULL,NULL);
// restore old situation and store 1rst solution to predictors
softbody_swap_state(ob,predict_pos,predict_vel);
// the following is to find out how good we were
// may be we can do smarter
// so now using the forces and jacobian we calculated before
// go only 1/2
softbody_apply_fake_implicit_forces(ob, forcetime/2.0f, NULL,NULL,NULL);
// explore situation here without redoing the jacobian
softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_SOLVE);
// go next 1/2
softbody_apply_fake_implicit_forces(ob, forcetime/2.0f,&loss_of_accuracy,predict_pos,predict_vel );
// now we have "loss_of_accuracy"
softbody_apply_goalsnap(ob);
if (loss_of_accuracy > SoftHeunTol) { /* error needs to be scaled to some quantity */
if (forcetime > forcetimemin){
forcetime = MAX2(forcetime / 2.0f,forcetimemin);
softbody_restore_prev_step(ob);
//printf("down,");
}
else {
timedone += forcetime;
}
}
else {
float newtime = forcetime * 1.5f; /* hope for 1.1 times better conditions in next step */
// all that 1/2 stepping was useless ... hum we know now ..
softbody_swap_state(ob,predict_pos,predict_vel);
if (0){//(sb->scratch->flag & SBF_DOFUZZY){
//if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */
newtime = forcetime;
//}
}
else {
if (loss_of_accuracy > SoftHeunTol/1.1f) { /* stay with this stepsize unless err really small */
newtime = forcetime;
}
}
timedone += forcetime;
newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin));
//if (newtime > forcetime) printf("up,");
if (forcetime > 0.0)
forcetime = MIN2(dtime - timedone,newtime);
else
forcetime = MAX2(dtime - timedone,newtime);
}
loops++;
// give away solver context within loop
if (sb_nlc)
{
if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n");
nlDeleteContext(sb_nlc);
sb_nlc = NULL;
}
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone);
}
/* ask for user break */
if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
}
// give away buffers
if (predict_pos) MEM_freeN(predict_pos);
if (predict_vel) MEM_freeN(predict_vel);
if(sb->solverflags & SBSO_MONITOR ){
if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
printf("\r needed %d steps/frame ",loops);
}
}/*SOLVER SELECT*/
else if (sb->solver_ID == 4)
{
/* do semi "fake" implicit euler */
NLContext *sb_nlc = NULL;
int nvar = 3*2*sb->totpoint;
int loops =0 ;
float forcetimemax = 1.0f; // this one needs 5 steps as a minimum
float forcetimemin = 0.001f;
float timedone =0.0; /* how far did we get without violating error condition */
/* loops = counter for emergency brake
* we don't want to lock up the system if physics fail
*/
SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops;
forcetime =forcetimemax; /* hope for integrating as fast as possible */
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){
float loss_of_accuracy=0;
// create new solver context for this loop
sb_nlc = (NLContext*)nlNewContext();
/* hum it smells like threading trouble */
nlSolverParameteri(NL_NB_VARIABLES, nvar);
nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE);
interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
softbody_store_step(ob); /* used for rolling back step guessing */
softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE);
softbody_apply_fake_implicit_forces(ob, forcetime,&loss_of_accuracy,NULL,NULL);
softbody_apply_goalsnap(ob);
if (loss_of_accuracy > SoftHeunTol) { /* error needs to be scaled to some quantity */
if (forcetime > forcetimemin){
forcetime = MAX2(forcetime / 2.0f,forcetimemin);
softbody_restore_prev_step(ob);
//printf("down,");
}
else {
timedone += forcetime;
}
}
else {
float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
if (0){//(sb->scratch->flag & SBF_DOFUZZY){
//if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */
newtime = forcetime;
//}
}
else {
if (loss_of_accuracy > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */
newtime = forcetime;
}
}
timedone += forcetime;
newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin));
//if (newtime > forcetime) printf("up,");
if (forcetime > 0.0)
forcetime = MIN2(dtime - timedone,newtime);
else
forcetime = MAX2(dtime - timedone,newtime);
}
loops++;
// give away solver context within loop
if (sb_nlc)
{
if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n");
nlDeleteContext(sb_nlc);
sb_nlc = NULL;
}
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone);
}
/* ask for user break */
if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
}
if(sb->solverflags & SBSO_MONITOR ){
if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
printf("\r needed %d steps/frame ",loops);
}
}/*SOLVER SELECT*/
else if (sb->solver_ID == 3){
/* do "stupid" semi "fake" implicit euler */
NLContext *sb_nlc = NULL;
int nvar = 3*2*sb->totpoint;
int loops =0 ;
float forcetimemax = 1.0f; // this one needs 5 steps as a minimum
float timedone =0.0; /* how far did we get without violating error condition */
/* loops = counter for emergency brake
* we don't want to lock up the system if physics fail
*/
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
forcetime =forcetimemax; /* hope for integrating as fast as possible */
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){
sb_nlc = (NLContext*)nlNewContext();
/* hum it smells like threading trouble */
nlSolverParameteri(NL_NB_VARIABLES, nvar);
nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE);
interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE);
softbody_apply_fake_implicit_forces(ob, forcetime, NULL,NULL,NULL);
softbody_apply_goalsnap(ob);
timedone += forcetime;
loops++;
if (sb_nlc)
{
if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n");
nlDeleteContext(sb_nlc);
sb_nlc = NULL;
}
/* ask for user break */
if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
}
}/*SOLVER SELECT*/
else{
/* do brute force explicit euler */
/* removed but left this branch for better integrators / solvers (BM) */
/* yah! Nicholas Guttenberg (NichG) here is the place to plug in */
}
printf("softbody no valid solver ID!");
}/*SOLVER SELECT*/
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
if (sct-sst > 0.5f) printf(" solver time %f %s \r",sct-sst,ob->id.name);

View File

@@ -6661,29 +6661,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
World *wrld;
if(main->versionfile != 244 || main->subversionfile < 2) {
Mesh *me;
for(sce= main->scene.first; sce; sce= sce->id.next)
sce->r.mode |= R_SSS;
/* Copy over old per-level multires vertex data
into a single vertex array in struct Multires */
for(me = main->mesh.first; me; me=me->id.next) {
if(me->mr) {
MultiresLevel *lvl = me->mr->levels.last;
if(lvl) {
me->mr->verts = lvl->verts;
lvl->verts = NULL;
/* Don't need the other vert arrays */
for(lvl = lvl->prev; lvl; lvl = lvl->prev) {
MEM_freeN(lvl->verts);
lvl->verts = NULL;
}
}
}
}
/* correct older action editors - incorrect scrolling */
for(sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
@@ -6737,6 +6717,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Lamp *la;
Material *ma;
ParticleSettings *part;
Mesh *me;
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
if ( !(main->versionfile==244 && main->subversionfile==3) &&
@@ -6766,14 +6747,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
}
break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data= (bStretchToConstraint *)curcon->data;
/* force recalc of rest-length */
data->orglength = 0;
}
break;
}
}
}
@@ -6805,14 +6778,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
}
break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data= (bStretchToConstraint *)curcon->data;
/* force recalc of rest-length */
data->orglength = 0;
}
break;
}
}
@@ -6876,6 +6841,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
/* Copy over old per-level multires vertex data
into a single vertex array in struct Multires */
for(me = main->mesh.first; me; me=me->id.next) {
if(me->mr && !me->mr->verts) {
MultiresLevel *lvl = me->mr->levels.last;
if(lvl) {
me->mr->verts = lvl->verts;
lvl->verts = NULL;
/* Don't need the other vert arrays */
for(lvl = lvl->prev; lvl; lvl = lvl->prev) {
MEM_freeN(lvl->verts);
lvl->verts = NULL;
}
}
}
}
if (main->versionfile != 245 || main->subversionfile < 1) {
for(la=main->lamp.first; la; la= la->id.next) {

View File

@@ -112,6 +112,7 @@ void insertkey_action(void);
void delete_action_keys(void);
void delete_action_channels(void);
void clean_action(void);
void sample_action_keys(void);
/* Column/Channel Key select */
void column_select_action_keys(int mode);

View File

@@ -54,6 +54,8 @@ struct Material *editnode_get_active_material(struct Material *ma);
struct bNode *editnode_get_active_idnode(struct bNodeTree *ntree, short id_code);
struct bNode *editnode_get_active(struct bNodeTree *ntree);
void node_rename(struct SpaceNode *snode);
void snode_tag_dirty(struct SpaceNode *snode);
void snode_set_context(struct SpaceNode *snode);
@@ -72,7 +74,7 @@ void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode);
void node_hide(struct SpaceNode *snode);
void node_read_renderlayers(struct SpaceNode *snode);
void clear_scene_in_nodes(struct Scene *sce);
void node_toggle_link(struct SpaceNode *snode);
void node_make_link(struct SpaceNode *snode);
void node_transform_ext(int mode, int unused);
void node_shader_default(struct Material *ma);
@@ -97,6 +99,8 @@ struct SpaceNode;
struct bNodeLink;
void node_draw_link(struct SpaceNode *snode, struct bNodeLink *link);
void node_rename_but(char *s);
void init_node_butfuncs(void);
/* exported to CMP and SHD nodes */

View File

@@ -90,7 +90,6 @@ typedef struct bPoseChannel {
*/
typedef struct bPose {
ListBase chanbase; /* list of pose channels */
struct bAction *poselib; /* poselib-action for this pose */
short flag, proxy_layer; /* proxy layer: copy from armature, gets synced */
@@ -104,6 +103,7 @@ typedef struct bPose {
*/
typedef struct bActionChannel {
struct bActionChannel *next, *prev;
struct Ipo *ipo; /* IPO block this action channel references */
ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */

View File

@@ -107,6 +107,7 @@ typedef struct bNode {
struct bNode *next, *prev, *new_node;
char name[32];
char username[32]; /* custom name defined by user */
short type, flag;
short done, level; /* both for dependency and sorting */
short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */
@@ -196,11 +197,13 @@ typedef struct NodeImageAnim {
} NodeImageAnim;
typedef struct NodeBlurData {
short sizex, sizey, samples, maxspeed, minspeed, pad1;
float fac;
short sizex, sizey;
short samples, maxspeed, minspeed, relative;
float fac, percentx, percenty;
short filtertype;
char bokeh, gamma;
int pad2;
int pad;
int image_in_width, image_in_height; /* needed for absolute/relative conversions */
} NodeBlurData;
typedef struct NodeDBlurData {

View File

@@ -129,10 +129,13 @@ typedef struct SoftBody {
minloops,
maxloops,
choke,
pad3,pad4,pad5
solver_ID,
pad4,pad5
;
struct SBScratch *scratch; /* scratch pad/cache on live time not saved in file */
float shearstiff;
float inpush;
} SoftBody;
/* pd->forcefield: Effector Fields types */

View File

@@ -22,7 +22,8 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
* Juho Vepsäläinen
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -556,16 +557,20 @@ static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf
static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
CompBuf *new, *img= in[0]->data;
NodeBlurData *nbd= node->storage;
if(img==NULL || out[0]->hasoutput==0)
return;
if(img==NULL) return;
/* store image in size that is needed for absolute/relative conversions on ui level */
nbd->image_in_width= img->x;
nbd->image_in_height= img->y;
if(out[0]->hasoutput==0) return;
if (((NodeBlurData *)node->storage)->filtertype == R_FILTER_FAST_GAUSS) {
CompBuf *new, *img = in[0]->data;
/*from eeshlo's original patch, removed to fit in with the existing blur node */
/*const float sx = in[1]->vec[0], sy = in[2]->vec[0];*/
NodeBlurData *nbd= node->storage;
const float sx = ((float)nbd->sizex)/2.0f, sy = ((float)nbd->sizey)/2.0f;
int c;

View File

@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): Björn C. Schaefer
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -123,6 +123,8 @@ bNodeType cmp_node_curve_vec= {
static bNodeSocketType cmp_node_curve_rgb_in[]= {
{ SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "Black Level", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "White Level", 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
@@ -157,7 +159,7 @@ static void do_curves_fac(bNode *node, float *out, float *in, float *fac)
static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
/* stack order input: fac, image */
/* stack order input: fac, image, black level, white level */
/* stack order output: image */
if(out[0]->hasoutput==0)
@@ -172,6 +174,8 @@ static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **i
CompBuf *cbuf= in[1]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec);
if(in[0]->vec[0] == 1.0)
composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
else

View File

@@ -1496,7 +1496,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f;
float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
float adapt_angle=0.0, adapt_pix=0.0, random;
float simplify[2];
int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0;
int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
@@ -1608,8 +1608,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
totpart=psys->totpart;
mesh_get_texspace(ob->data, loc_tex, NULL, size_tex);
if(psys->pathcache){
path_possible=1;
keys_possible=1;
@@ -1789,12 +1787,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
}
}
if(orco) {
orco[0] = (orco[0]-loc_tex[0])/size_tex[0];
orco[1] = (orco[1]-loc_tex[1])/size_tex[1];
orco[2] = (orco[2]-loc_tex[2])/size_tex[2];
}
/* surface normal shading setup */
if(ma->mode_l & MA_STR_SURFDIFF) {
Mat3MulVecfl(nmat, nor);

View File

@@ -3181,7 +3181,7 @@ static void object_panel_deflection(Object *ob)
PartDeflect *pd= ob->pd;
but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
// uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
if(pd->deflect) {
uiDefBut(block, LABEL, 0, "Particles", 160,140,75,20, NULL, 0.0, 0, 0, 0, "");
@@ -3445,6 +3445,12 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v)
allqueue(REDRAWBUTSEDIT, 0);
}
#ifdef _work_on_sb_solver
static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some german teachers %x1|STU ip semi implicit euler%x3|SI1 (half step)adaptive semi implict euler %x2|SI2 (use dv)adaptive semi implict euler %x4|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0";
#else
static char sbsolvers[] = "STU PID semi implicit euler%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0";
#endif
static void object_softbodies_II(Object *ob)
{
SoftBody *sb=ob->soft;
@@ -3462,7 +3468,7 @@ static void object_softbodies_II(Object *ob)
}
block= uiNewBlock(&curarea->uiblocks, "object_softbodies_II", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Soft Body", "Physics");
if(uiNewPanel(curarea, block, "Soft Body Collision", "Physics", 651, 0, 318, 204)==0) return;
if(uiNewPanel(curarea, block, "Soft Body Col&Solv", "Physics", 651, 0, 318, 204)==0) return;
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
@@ -3534,10 +3540,13 @@ static void object_softbodies_II(Object *ob)
uiBlockEndAlign(block);
/*SOLVER SETTINGS*/
uiDefButF(block, NUM, B_DIFF, "Error Lim:", 10,100,130,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed");
uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 140,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation");
uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,100,130,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable");
uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints");
uiBlockBeginAlign(block);
uiDefButS(block, MENU, B_DIFF, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver");
uiDefButF(block, NUM, B_DIFF, "Error Lim:", 60,100,130,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed");
uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 190,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation");
uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable");
uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 300,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints");
uiBlockEndAlign(block);
uiDefButS(block, NUM, B_DIFF, "MinS:", 10,80,100,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame ");
uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame ");
uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target ");
@@ -3619,6 +3628,7 @@ static void object_softbodies(Object *ob)
else
but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become soft body");
uiButSetFunc(but, object_softbodies__enable, ob, NULL);
}
@@ -3721,11 +3731,15 @@ static void object_softbodies(Object *ob)
uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_DIFF, "CEdge", 220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too");
uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_DIFF, "CFace", 265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning ");
uiDefButF(block, NUM, B_DIFF, "E Stiff:", 10,30,150,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness");
uiDefButF(block, NUM, B_DIFF, "E Damp:", 160,30,150,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction");
uiDefButS(block, NUM, B_DIFF, "Aero:", 10,10,150,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'");
uiDefButF(block, NUM, B_DIFF, "E Pull:", 10,30,100,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness");
uiDefButF(block, NUM, B_DIFF, "E Push:", 110,30,100,20, &sb->inpush, 0.0, 0.999, 10, 0, "Edge spring stiffness");
uiDefButF(block, NUM, B_DIFF, "E Damp:", 210,30,100,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction");
uiDefButS(block, NUM, B_DIFF, "Aero:", 10,10,100,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'");
if(ob->type==OB_MESH) {
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Rigidity:", 160,10,150,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Strenght of Springs over 2 Edges");
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Bend:", 110,10,100,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Strenght of Springs over 2 Edges");
if (*softflag & OB_SB_QUADS){
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0, 1.0, 10, 0, "Strenght of Springs over 2 Edges");
}
}
else sb->secondspring = 0;
uiDefBut(block, LABEL, 0, "",10,10,1,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/

View File

@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): David Millan Escriva, Juho Vepsäläinen
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -1047,12 +1047,41 @@ static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNo
return 19;
}
static void node_blur_relative_cb(void *node, void *poin2)
{
bNode *nodev= node;
NodeBlurData *nbd= nodev->storage;
if(nbd->image_in_width != 0){
if(nbd->relative){ /* convert absolute values to relative */
nbd->percentx= (float)(nbd->sizex)/nbd->image_in_width;
nbd->percenty= (float)(nbd->sizey)/nbd->image_in_height;
}else{ /* convert relative values to absolute */
nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
}
}
allqueue(REDRAWNODE, 0);
}
static void node_blur_update_sizex_cb(void *node, void *poin2)
{
bNode *nodev= node;
NodeBlurData *nbd= nodev->storage;
nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
}
static void node_blur_update_sizey_cb(void *node, void *poin2)
{
bNode *nodev= node;
NodeBlurData *nbd= nodev->storage;
nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
}
static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
NodeBlurData *nbd= node->storage;
uiBut *bt;
short dy= butr->ymin+38;
short dy= butr->ymin+58;
short dx= (butr->xmax-butr->xmin)/2;
char str[256];
@@ -1074,15 +1103,33 @@ static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node
uiBlockBeginAlign(block);
}
dy-=19;
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
butr->xmin, dy, dx, 19,
&nbd->sizex, 0, 256, 0, 0, "");
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
butr->xmin+dx, dy, dx, 19,
&nbd->sizey, 0, 256, 0, 0, "");
bt= uiDefButS(block, TOG, B_NOP, "Relative",
butr->xmin, dy, dx*2, 19,
&nbd->relative, 0, 0, 0, 0, "Use relative (percent) values to define blur radius");
uiButSetFunc(bt, node_blur_relative_cb, node, NULL);
dy-=19;
if(nbd->relative) {
bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "X:",
butr->xmin, dy, dx, 19,
&nbd->percentx, 0.0f, 1.0f, 0, 0, "");
uiButSetFunc(bt, node_blur_update_sizex_cb, node, NULL);
bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Y:",
butr->xmin+dx, dy, dx, 19,
&nbd->percenty, 0.0f, 1.0f, 0, 0, "");
uiButSetFunc(bt, node_blur_update_sizey_cb, node, NULL);
}
else {
uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
butr->xmin, dy, dx, 19,
&nbd->sizex, 0, 256, 0, 0, "");
uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
butr->xmin+dx, dy, dx, 19,
&nbd->sizey, 0, 256, 0, 0, "");
}
uiBlockEndAlign(block);
}
return 57;
return 77;
}
static int node_composit_buts_dblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
@@ -1996,6 +2043,45 @@ void init_node_butfuncs(void)
/* ************** Generic drawing ************** */
void node_rename_but(char *s)
{
uiBlock *block;
ListBase listb={0, 0};
int dy, x1, y1, sizex=80, sizey=30;
short pivot[2], mval[2], ret=0;
getmouseco_sc(mval);
pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
warp_pointer(pivot[0], pivot[1]);
mywinset(G.curscreen->mainwin);
x1= pivot[0]-sizex+10;
y1= pivot[1]-sizey/2;
dy= sizey/2;
block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
/* buttons have 0 as return event, to prevent menu to close on hotkeys */
uiBlockBeginAlign(block);
uiDefBut(block, TEX, B_NOP, "Name: ", (short)(x1),(short)(y1+dy), 150, 19, s, 0.0, 19.0, 0, 0, "Node user name");
uiBlockEndAlign(block);
uiDefBut(block, BUT, 32767, "OK", (short)(x1+150), (short)(y1+dy), 29, 19, NULL, 0, 0, 0, 0, "");
uiBoundsBlock(block, 2);
ret= uiDoBlocks(&listb, 0, 0);
}
static void draw_nodespace_grid(SpaceNode *snode)
{
float start, step= 25.0f;
@@ -2439,6 +2525,7 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node)
rctf *rct= &node->totr;
float slen, iconofs;
int ofs, color_id= node_get_colorid(node);
char showname[128];
uiSetRoundBox(15-4);
ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT);
@@ -2517,8 +2604,18 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node)
BIF_ThemeColor(TH_TEXT);
ui_rasterpos_safe(rct->xmin+19.0f, rct->ymax-NODE_DY+5.0f, snode->aspect);
snode_drawstring(snode, node->name, (int)(iconofs - rct->xmin-18.0f));
if(node->username[0]) {
strcpy(showname,"(");
strcat(showname, node->username);
strcat(showname,") ");
strcat(showname, node->name);
}
else
strcpy(showname, node->name);
snode_drawstring(snode, showname, (int)(iconofs - rct->xmin-18.0f));
/* body */
BIF_ThemeColor4(TH_NODE);
glEnable(GL_BLEND);
@@ -2633,13 +2730,14 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node)
}
void node_draw_hidden(SpaceNode *snode, bNode *node)
static void node_draw_hidden(SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
rctf *rct= &node->totr;
float dx, centy= 0.5f*(rct->ymax+rct->ymin);
float hiddenrad= 0.5f*(rct->ymax-rct->ymin);
int color_id= node_get_colorid(node);
char showname[128];
/* shadow */
uiSetRoundBox(15);
@@ -2673,7 +2771,17 @@ void node_draw_hidden(SpaceNode *snode, bNode *node)
if(node->miniwidth>0.0f) {
ui_rasterpos_safe(rct->xmin+21.0f, centy-4.0f, snode->aspect);
snode_drawstring(snode, node->name, (int)(rct->xmax - rct->xmin-18.0f -12.0f));
if(node->username[0]) {
strcpy(showname,"(");
strcat(showname, node->username);
strcat(showname,") ");
strcat(showname, node->name);
}
else
strcpy(showname, node->name);
snode_drawstring(snode, showname, (int)(rct->xmax - rct->xmin-18.0f -12.0f));
}
/* scale widget thing */
@@ -2875,6 +2983,7 @@ static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode)
bNodeTree *ngroup= (bNodeTree *)gnode->id;
bNodeSocket *sock;
rctf rect= gnode->totr;
char showname[128];
/* backdrop header */
glEnable(GL_BLEND);
@@ -2898,7 +3007,17 @@ static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode)
/* backdrop title */
BIF_ThemeColor(TH_TEXT_HI);
ui_rasterpos_safe(rect.xmin+8.0f, rect.ymax+5.0f, snode->aspect);
BIF_DrawString(snode->curfont, ngroup->id.name+2, 0);
if(gnode->username[0]) {
strcpy(showname,"(");
strcat(showname, gnode->username);
strcat(showname,") ");
strcat(showname, ngroup->id.name+2);
}
else
strcpy(showname, ngroup->id.name+2);
BIF_DrawString(snode->curfont, showname, 0);
/* links from groupsockets to the internal nodes */
node_draw_group_links(snode, gnode);

View File

@@ -3860,8 +3860,8 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
if(psys->childcache==0)
psys_cache_child_paths(ob, psys, CFRA, 0);
}
else if(psys->childcache)
free_child_path_cache(psys);
else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
free_child_path_cache(psys);
if((G.vd->flag & V3D_ZBUF_SELECT)==0)
glDisable(GL_DEPTH_TEST);
@@ -3905,13 +3905,14 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
}
glEnable(GL_LIGHTING);
if(psys->part->draw_as == PART_DRAW_PATH) {
for(i=0, path=psys->childcache; i<totchild; i++,path++){
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
for(i=0, path=psys->childcache; i<totchild; i++,path++){
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
}
}
glDisable(GL_COLOR_MATERIAL);

View File

@@ -160,9 +160,9 @@ void remake_action_ipos (bAction *act)
testhandles_ipocurve(icu);
}
}
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
if (conchan->ipo) {
for (icu = conchan->ipo->curve.first; icu; icu=icu->next){
for (icu = conchan->ipo->curve.first; icu; icu=icu->next) {
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
}
@@ -962,7 +962,7 @@ void insertkey_action(void)
ListBase act_data = {NULL, NULL};
bActListElem *ale;
int filter;
/* ask user what to keyframe */
mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2");
if (mode <= 0) return;
@@ -1047,7 +1047,7 @@ void delete_action_keys (void)
allqueue(REDRAWNLA, 0);
}
/* delete selected keyframes */
/* delete selected action-channels (only achans and conchans are considered) */
void delete_action_channels (void)
{
ListBase act_data = {NULL, NULL};
@@ -1142,6 +1142,99 @@ void clean_action (void)
allqueue(REDRAWNLA, 0);
}
/* little cache for values... */
typedef struct tempFrameValCache {
float frame, val;
} tempFrameValCache;
/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
void sample_action_keys (void)
{
ListBase act_data = {NULL, NULL};
bActListElem *ale;
int filter;
void *data;
short datatype;
/* sanity checks */
data= get_action_context(&datatype);
if (data == NULL) return;
/* filter data */
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
actdata_filter(&act_data, filter, data, datatype);
/* loop through filtered data and add keys between selected keyframes on every frame */
for (ale= act_data.first; ale; ale= ale->next) {
IpoCurve *icu= (IpoCurve *)ale->key_data;
BezTriple *bezt, *start=NULL, *end=NULL;
tempFrameValCache *value_cache, *fp;
int sfra, range;
int i, n;
/* find selected keyframes... once pair has been found, add keyframes */
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
/* check if selected, and which end this is */
if (BEZSELECTED(bezt)) {
if (start) {
/* set end */
end= bezt;
/* cache values then add keyframes using these values, as adding
* keyframes while sampling will affect the outcome...
*/
range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
sfra= (int)( floor(start->vec[1][0]) );
if (range) {
value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
/* sample values */
for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
fp->frame= (float)(sfra + n);
fp->val= eval_icu(icu, fp->frame);
}
/* add keyframes with these */
for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
insert_vert_icu(icu, fp->frame, fp->val, 1);
}
/* free temp cache */
MEM_freeN(value_cache);
}
/* as we added keyframes, we need to compensate so that bezt is at the right place */
bezt = icu->bezt + i + range - 1;
i += (range - 1);
/* bezt was selected, so it now marks the start of a whole new chain to search */
start= bezt;
end= NULL;
}
else {
/* just set start keyframe */
start= bezt;
end= NULL;
}
}
}
/* recalculate channel's handles? */
calchandles_ipocurve(icu);
}
/* admin and redraws */
BLI_freelistN(&act_data);
BIF_undo_push("Sample Action Keys");
allqueue(REMAKEIPO, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
}
/* **************************************************** */
/* COPY/PASTE FOR ACTIONS */
/* - The copy/paste buffer currently stores a set of Action Channels, with temporary
@@ -3087,7 +3180,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case OKEY:
clean_action();
if (G.qual & LR_ALTKEY)
sample_action_keys();
else
clean_action();
break;
case PKEY:

View File

@@ -5653,22 +5653,24 @@ void delete_ipo_keys(Ipo *ipo)
IpoCurve *icu, *next;
int i;
if (!ipo)
if (ipo == NULL)
return;
for (icu=ipo->curve.first; icu; icu=next){
for (icu= ipo->curve.first; icu; icu= next) {
next = icu->next;
for (i=0; i<icu->totvert; i++){
if (icu->bezt[i].f2 & 1){
// Delete the item
memcpy (&icu->bezt[i], &icu->bezt[i+1], sizeof (BezTriple)*(icu->totvert-i-1));
/* Delete selected BezTriples */
for (i=0; i<icu->totvert; i++) {
if (icu->bezt[i].f2 & SELECT) {
memcpy(&icu->bezt[i], &icu->bezt[i+1], sizeof(BezTriple)*(icu->totvert-i-1));
icu->totvert--;
i--;
}
}
if (!icu->totvert){
/* Delete the curve */
BLI_remlink( &(ipo->curve), icu);
/* Only delete if there isn't an ipo-driver still hanging around on an empty curve */
if (icu->totvert==0 && icu->driver==NULL) {
BLI_remlink(&ipo->curve, icu);
free_ipo_curve(icu);
}
}

View File

@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): David Millan Escriva, Juho Vepsäläinen
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -1083,7 +1083,29 @@ static void scale_node(SpaceNode *snode, bNode *node)
allqueue(REDRAWNODE, 1);
}
/* ******************** rename ******************* */
void node_rename(SpaceNode *snode)
{
bNode *node, *rename_node;
short found_node= 0;
/* check if a node is selected */
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
found_node= 1;
break;
}
}
if(found_node) {
rename_node= nodeGetActive(snode->edittree);
node_rename_but((char *)rename_node->username);
BIF_undo_push("Rename Node");
allqueue(REDRAWNODE, 1);
}
}
/* ********************** select ******************** */
@@ -1855,34 +1877,31 @@ void node_select_linked(SpaceNode *snode, int out)
allqueue(REDRAWNODE, 1);
}
void node_toggle_link(SpaceNode *snode)
/* makes a link between selected output and input sockets */
void node_make_link(SpaceNode *snode)
{
bNode *fromnode, *tonode;
bNodeLink *remlink, *link;
bNodeLink *link;
bNodeSocket *outsock= snode->edittree->selout;
bNodeSocket *insock= snode->edittree->selin;
if(!insock || !outsock) return;
if(nodeFindLink(snode->edittree, outsock, insock)) return;
remlink= nodeFindLink(snode->edittree, outsock, insock);
if(remlink) nodeRemLink(snode->edittree, remlink);
else {
if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
nodeFindNode(snode->edittree, insock, &tonode, NULL)) {
link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
NodeTagChanged(snode->edittree, tonode);
node_remove_extra_links(snode, insock, link);
}
else return;
if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
nodeFindNode(snode->edittree, insock, &tonode, NULL)) {
link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
NodeTagChanged(snode->edittree, tonode);
node_remove_extra_links(snode, insock, link);
}
else return;
ntreeSolveOrder(snode->edittree);
snode_verify_groups(snode);
snode_handle_recalc(snode);
allqueue(REDRAWNODE, 0);
BIF_undo_push("Toggle Link");
BIF_undo_push("Make Link Between Sockets");
}
static void node_border_link_delete(SpaceNode *snode)
@@ -2278,7 +2297,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
snode_handle_recalc(snode);
break;
case FKEY:
node_toggle_link(snode);
node_make_link(snode);
break;
case GKEY:
if(fromlib) fromlib= -1;
@@ -2308,8 +2327,12 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
node_select_linked(snode, G.qual==LR_SHIFTKEY);
break;
case RKEY:
if(okee("Read saved Render Layers"))
node_read_renderlayers(snode);
if(G.qual==LR_CTRLKEY) {
node_rename(snode);
} else{
if(okee("Read saved Render Layers"))
node_read_renderlayers(snode);
}
break;
case DELKEY:
case XKEY:

View File

@@ -2392,6 +2392,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe
ekey->time = &hkey->time;
}
pa->size= 1.0f;
initialize_particle(pa,i,ob,psys,psmd);
reset_particle(pa,psys,psmd,ob,0.0,1.0,0,0,0);
pa->flag |= PARS_EDIT_RECALC;

View File

@@ -117,7 +117,8 @@ enum {
enum {
ACTMENU_KEY_DUPLICATE = 0,
ACTMENU_KEY_DELETE,
ACTMENU_KEY_CLEAN
ACTMENU_KEY_CLEAN,
ACTMENU_KEY_SAMPLEKEYS
};
enum {
@@ -1006,11 +1007,14 @@ static void do_action_keymenu(void *arg, int event)
duplicate_action_keys();
break;
case ACTMENU_KEY_DELETE:
delete_action_keys ();
delete_action_keys();
break;
case ACTMENU_KEY_CLEAN:
clean_action();
break;
case ACTMENU_KEY_SAMPLEKEYS:
sample_action_keys();
break;
}
}
@@ -1052,6 +1056,11 @@ static uiBlock *action_keymenu(void *arg_unused)
"Clean Action|O", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_CLEAN, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Sample Keys|Alt O", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_SAMPLEKEYS, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");

View File

@@ -23,7 +23,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): David Millan Escriva, Juho Vepsäläinen
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -513,8 +513,11 @@ static void do_node_nodemenu(void *arg, int event)
case 10: /* execute */
addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
break;
case 11: /* toggle link */
node_toggle_link(snode);
case 11: /* make link */
node_make_link(snode);
break;
case 12: /* rename */
node_rename(snode);
break;
}
@@ -541,7 +544,7 @@ static uiBlock *node_nodemenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Toggle Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
@@ -552,6 +555,7 @@ static uiBlock *node_nodemenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide/Unhide|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");

View File

@@ -1674,13 +1674,14 @@ static TBitem tb_node_node[]= {
{ 0, "Duplicate|Shift D", TB_SHIFT|'d', NULL},
{ 0, "Delete|X", 'x', NULL},
{ 0, "SEPR", 0, NULL},
{ 0, "Toggle Link|F", 'f', NULL},
{ 0, "Make Link|F", 'f', NULL},
{ 0, "SEPR", 0, NULL},
{ 0, "Make Group|Ctrl G", TB_CTRL|'g', NULL},
{ 0, "Ungroup|Alt G", TB_ALT|'g', NULL},
{ 0, "Edit Group|Tab", TB_TAB, NULL},
{ 0, "SEPR", 0, NULL},
{ 0, "Hide/Unhide|H", 'h', NULL},
{ 0, "Rename|Ctrl R", TB_CTRL|'r', NULL},
{ 0, "SEPR", 0, NULL},
{ 0, "Read Saved Render Results|R", 'r', NULL},
{ 0, "Show Cyclic Dependencies|C", 'c', NULL},