Fix & further implementation of Proportional editing;

- made generic 'calc distance' function for it
- added generic call to sort TransData with selection first, for speedup
  of propmode calculus
- removed most propmode exceptions from code, only used for counting now
- all editmode transdata conversion function structured identical
This commit is contained in:
2005-03-06 19:25:58 +00:00
parent a14d5c57be
commit b6cb442c2a

View File

@@ -129,26 +129,73 @@ int LastMode = TFM_TRANSLATION;
/* ************************** Functions *************************** */
/* ************************** CONVERSIONS ************************* */
static int allocTransData(void)
static void sort_trans_data(TransInfo *t)
{
int count, mode=0;
countall();
if(mode) count= G.totvert;
else count= G.totvertsel;
printf("count: %d\n", count);
if(G.totvertsel==0) {
count= 0;
return count;
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++;
}
Trans.total = count;
Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(EditMode)");
return count;
}
/* 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)
{
TransData *tob;
int a;
for(a=0, tob= t->data; a<t->total; a++, tob++) {
tob->dist= 0.0f; // init, it was mallocced
if((tob->flag & TD_SELECTED)==0) {
TransData *td;
int i;
float dist, vec[3];
tob->dist = -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);
dist = Normalise(vec);
if (tob->dist == -1.0f) {
tob->dist = dist;
}
else if (dist < tob->dist) {
tob->dist = dist;
}
}
else break; // by definition transdata has selected items in beginning
}
}
}
}
/* ************************** CONVERSIONS ************************* */
void createTransTexspace(void)
{
TransData *td;
@@ -238,7 +285,6 @@ static void add_pose_transdata(ListBase *lb, Object *ob, TransData **tdp)
VECCOPY(td->center, vec);
td->ob = ob;
td->dist= 0.0f;
td->flag= TD_SELECTED|TD_USEQUAT;
td->loc = bone->loc;
VECCOPY(td->iloc, bone->loc);
@@ -360,8 +406,6 @@ static void createTransArmatureVerts(void)
td->ext = NULL;
td->tdi = NULL;
td->dist = 0.0f;
td++;
}
if (ebo->flag & BONE_ROOTSEL){
@@ -375,8 +419,6 @@ static void createTransArmatureVerts(void)
td->ext = NULL;
td->tdi = NULL;
td->dist = 0.0f;
td++;
}
@@ -389,25 +431,35 @@ static void createTransMBallVerts(void)
TransData *td;
TransDataExtension *tx;
float mtx[3][3], smtx[3][3];
int count;
int count=0, countsel=0;
int propmode = G.f & G_PROPORTIONAL;
count = allocTransData();
if (!count) return;
/* 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) Trans.total = count;
else Trans.total = countsel;
Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(MBall EditMode)");
tx = MEM_mallocN(Trans.total*sizeof(TransDataExtension), "MetaElement_TransExtension");
Mat3CpyMat4(mtx, G.obedit->obmat);
Mat3Inv(smtx, mtx);
td = Trans.data;
ml= editelems.first;
while(ml) {
if(ml->flag & SELECT) {
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);
td->flag= TD_SELECTED;
if(ml->flag & SELECT) td->flag= TD_SELECTED;
else td->flag= 0;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
@@ -421,12 +473,9 @@ static void createTransMBallVerts(void)
tx->rot = NULL;
td->dist = 0.0f;
td++;
tx++;
}
ml= ml->next;
}
}
@@ -438,122 +487,141 @@ static void createTransCurveVerts(void)
BPoint *bp;
float mtx[3][3], smtx[3][3];
int a;
int count=0;
int mode = 0; /*This used for. . .what?*/
//int proptrans= 0;
int count=0, countsel=0;
int propmode = G.f & G_PROPORTIONAL;
count = allocTransData();
if (!count) return;
/* 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) {
if(bezt->f1 & 1) countsel++;
if(bezt->f2 & 1) countsel++;
if(bezt->f3 & 1) countsel++;
if(propmode) count+= 3;
}
}
}
else {
for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
if(bp->hide==0) {
if(propmode) count++;
if(bp->f1 & 1) countsel++;
}
}
}
}
/* note: in prop mode we need at least 1 selected */
if (countsel==0) return;
if(propmode) Trans.total = count;
else Trans.total = countsel;
Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(Curve EditMode)");
Mat3CpyMat4(mtx, G.obedit->obmat);
Mat3Inv(smtx, mtx);
td = Trans.data;
nu= editNurb.first;
while(nu) {
for(nu= editNurb.first; nu; nu= nu->next) {
if((nu->type & 7)==CU_BEZIER) {
a= nu->pntsu;
bezt= nu->bezt;
while(a--) {
for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
if(bezt->hide==0) {
if(mode==1 || (bezt->f1 & 1)) {
if(propmode || (bezt->f1 & 1)) {
VECCOPY(td->iloc, bezt->vec[0]);
td->loc= bezt->vec[0];
VECCOPY(td->center, td->loc);
td->flag= TD_SELECTED;
if(bezt->f1 & 1) td->flag= TD_SELECTED;
else td->flag= 0;
td->ext = NULL;
td->tdi = NULL;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->dist = 0.0f;
td++;
count++;
}
if(mode==1 || (bezt->f2 & 1)) {
if(propmode || (bezt->f2 & 1)) {
VECCOPY(td->iloc, bezt->vec[1]);
td->loc= bezt->vec[1];
VECCOPY(td->center, td->loc);
td->flag= TD_SELECTED;
if(bezt->f2 & 1) td->flag= TD_SELECTED;
else td->flag= 0;
td->ext = NULL;
td->tdi = NULL;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->dist = 0.0f;
td++;
count++;
}
if(mode==1 || (bezt->f3 & 1)) {
if(propmode || (bezt->f3 & 1)) {
VECCOPY(td->iloc, bezt->vec[2]);
td->loc= bezt->vec[2];
VECCOPY(td->center, td->loc);
td->flag= TD_SELECTED;
if(bezt->f3 & 1) td->flag= TD_SELECTED;
else td->flag= 0;
td->ext = NULL;
td->tdi = NULL;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->dist = 0.0f;
td++;
count++;
}
}
bezt++;
}
}
else {
a= nu->pntsu*nu->pntsv;
bp= nu->bp;
while(a--) {
for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
if(bp->hide==0) {
if(mode==1 || (bp->f1 & 1)) {
if(propmode || (bp->f1 & 1)) {
VECCOPY(td->iloc, bp->vec);
td->loc= bp->vec;
VECCOPY(td->center, td->loc);
td->flag= TD_SELECTED;
if(bp->f1 & 1) td->flag= TD_SELECTED;
else td->flag= 0;
td->ext = NULL;
td->tdi = NULL;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->dist = 0.0f;
td++;
count++;
}
}
bp++;
}
}
nu= nu->next;
}
}
static void createTransLatticeVerts(void)
{
TransData *td = NULL;
int count = 0;
BPoint *bp;
float mtx[3][3], smtx[3][3];
int mode = 0; /*This used for proportional editing*/
/*should find a function that does this. . . what else is this used for? I DONT KNOW!*/
int a;
//int proptrans= 0;
int count=0, countsel=0;
int propmode = G.f & G_PROPORTIONAL;
bp= editLatt->def;
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
while(a--) {
if(bp->f1 & 1) countsel++;
if(propmode) count++;
bp++;
}
/* note: in prop mode we need at least 1 selected */
if (countsel==0) return;
count = allocTransData();
if (!count) return;
if(propmode) Trans.total = count;
else Trans.total = countsel;
Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(Lattice EditMode)");
Mat3CpyMat4(mtx, G.obedit->obmat);
Mat3Inv(smtx, mtx);
@@ -562,21 +630,19 @@ static void createTransLatticeVerts(void)
bp= editLatt->def;
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
while(a--) {
if(mode==1 || (bp->f1 & 1)) {
if(propmode || (bp->f1 & 1)) {
if(bp->hide==0) {
VECCOPY(td->iloc, bp->vec);
td->loc= bp->vec;
VECCOPY(td->center, td->loc);
td->flag= TD_SELECTED;
if(bp->f1 & 1) td->flag= TD_SELECTED;
else td->flag= 0;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->ext = NULL;
td->tdi = NULL;
td->dist = 0.0f;
td++;
count++;
}
@@ -598,20 +664,17 @@ static void VertsToTransData(TransData *td, EditVert *eve)
static void createTransEditVerts(void)
{
TransData *tob = NULL;
int totsel = 0;
EditMesh *em = G.editMesh;
EditVert *eve;
float mtx[3][3], smtx[3][3];
/*should find a function that does this. . .*/
// int proptrans= 0;
int count=0, countsel=0;
int propmode = G.f & G_PROPORTIONAL;
// 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)) {
if(eve->h==0 && (eve->f & SELECT))
eve->f1= SELECT;
Trans.total++;
}
else
eve->f1= 0;
}
@@ -623,9 +686,6 @@ static void createTransEditVerts(void)
if(eed->h==0 && (eed->f & SELECT))
eed->v1->f1= eed->v2->f1= SELECT;
}
for(eve= em->verts.first; eve; eve= eve->next)
if(eve->f1)
Trans.total++;
}
else {
EditFace *efa;
@@ -636,77 +696,38 @@ static void createTransEditVerts(void)
if(efa->v4) efa->v4->f1= SELECT;
}
}
for(eve= em->verts.first; eve; eve= eve->next)
if(eve->f1)
Trans.total++;
}
totsel = Trans.total;
/* proportional edit exception... */
if((G.f & G_PROPORTIONAL) && Trans.total) {
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && (!(eve->f1 & SELECT))) {
eve->f1 = 2;
Trans.total++;
}
/* now we can count */
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0) {
if(eve->f1) countsel++;
if(propmode) count++;
}
}
/* and now make transverts */
if (!Trans.total) return;
/* note: in prop mode we need at least 1 selected */
if (countsel==0) return;
if(propmode) Trans.total = count;
else Trans.total = countsel;
tob= Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(Mesh EditMode)");
Mat3CpyMat4(mtx, G.obedit->obmat);
Mat3Inv(smtx, mtx);
tob = Trans.data = MEM_mallocN(Trans.total*sizeof(TransData), "TransEditVert");
for (eve=em->verts.first; eve; eve=eve->next)
{
if (eve->f1 == SELECT) {
VertsToTransData(tob, eve);
tob->flag |= TD_SELECTED;
Mat3CpyMat3(tob->smtx, smtx);
Mat3CpyMat3(tob->mtx, mtx);
tob->dist = 0.0f;
tob++;
}
}
/* PROPORTIONAL*/
if (G.f & G_PROPORTIONAL) {
for (eve=em->verts.first; eve; eve=eve->next)
{
TransData *td;
int i;
float dist, vec[3];
if (eve->f1 == 2) {
for (eve=em->verts.first; eve; eve=eve->next) {
if(eve->h==0) {
if(propmode || eve->f1) {
VertsToTransData(tob, eve);
if(eve->f1) tob->flag |= TD_SELECTED;
Mat3CpyMat3(tob->smtx, smtx);
Mat3CpyMat3(tob->mtx, mtx);
tob->dist = -1;
td = Trans.data;
for (i = 0; i < totsel; i++, td++) {
VecSubf(vec, tob->center, td->center);
Mat3MulVecfl(mtx, vec);
dist = Normalise(vec);
if (tob->dist == -1) {
tob->dist = dist;
}
else if (dist < tob->dist) {
tob->dist = dist;
}
}
tob++;
}
}
}
}
}
@@ -1065,7 +1086,6 @@ static void createTransObject(void)
td->flag= TD_SELECTED|TD_OBJECT;
td->ext = tx;
td->dist = 0.0f;
/* store ipo keys? */
if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
@@ -1153,6 +1173,12 @@ static void createTransData(TransInfo *t)
else {
printf("not done yet! only have mesh surface curve\n");
}
if(G.f & G_PROPORTIONAL) {
sort_trans_data(&Trans); // makes selected become first in array
set_prop_dist(&Trans);
}
}
else {
createTransObject();