Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <math.h> 00034 #include <string.h> 00035 00036 #ifndef WIN32 00037 #include <unistd.h> 00038 #else 00039 #include <io.h> 00040 #endif 00041 #include <stdlib.h> 00042 00043 #include "DNA_key_types.h" 00044 #include "DNA_object_types.h" 00045 #include "DNA_scene_types.h" 00046 #include "DNA_anim_types.h" 00047 00048 #include "MEM_guardedalloc.h" 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_math.h" 00052 #include "BLI_dynstr.h" 00053 #include "BLI_rand.h" 00054 #include "BLI_utildefines.h" 00055 #include "BLI_ghash.h" 00056 00057 #include "BKE_context.h" 00058 #include "BKE_curve.h" 00059 #include "BKE_depsgraph.h" 00060 #include "BKE_fcurve.h" 00061 #include "BKE_global.h" 00062 #include "BKE_key.h" 00063 #include "BKE_library.h" 00064 #include "BKE_main.h" 00065 #include "BKE_report.h" 00066 #include "BKE_animsys.h" 00067 #include "BKE_action.h" 00068 00069 #include "WM_api.h" 00070 #include "WM_types.h" 00071 00072 #include "ED_keyframes_edit.h" 00073 #include "ED_object.h" 00074 #include "ED_screen.h" 00075 #include "ED_transform.h" 00076 #include "ED_types.h" 00077 #include "ED_util.h" 00078 #include "ED_view3d.h" 00079 #include "ED_curve.h" 00080 00081 #include "curve_intern.h" 00082 00083 #include "UI_interface.h" 00084 #include "UI_resources.h" 00085 00086 #include "RNA_access.h" 00087 #include "RNA_define.h" 00088 #include "RNA_enum_types.h" 00089 00090 /* Undo stuff */ 00091 typedef struct { 00092 ListBase nubase; 00093 void *lastsel; 00094 GHash *undoIndex; 00095 ListBase fcurves, drivers; 00096 int actnu; 00097 } UndoCurve; 00098 00099 /* Definitions needed for shape keys */ 00100 typedef struct { 00101 void *orig_cv; 00102 int key_index, nu_index, pt_index; 00103 int switched; 00104 Nurb *orig_nu; 00105 } CVKeyIndex; 00106 00107 void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus); 00108 static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus); 00109 00110 /* still need to eradicate a few :( */ 00111 #define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name) 00112 00113 static float nurbcircle[8][2]= { 00114 {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0}, 00115 {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0} 00116 }; 00117 00118 ListBase *object_editcurve_get(Object *ob) 00119 { 00120 if(ob && ELEM(ob->type, OB_CURVE, OB_SURF)) { 00121 Curve *cu= ob->data; 00122 return &cu->editnurb->nurbs; 00123 } 00124 return NULL; 00125 } 00126 00127 /* this replaces the active flag used in uv/face mode */ 00128 static void set_actNurb(Object *obedit, Nurb *nu) 00129 { 00130 Curve *cu= obedit->data; 00131 00132 if(nu==NULL) 00133 cu->actnu = -1; 00134 else { 00135 ListBase *nurbs= curve_editnurbs(cu); 00136 cu->actnu = BLI_findindex(nurbs, nu); 00137 } 00138 } 00139 00140 static Nurb *get_actNurb(Object *obedit) 00141 { 00142 Curve *cu= obedit->data; 00143 ListBase *nurbs= curve_editnurbs(cu); 00144 00145 return BLI_findlink(nurbs, cu->actnu); 00146 } 00147 00148 /* ******************* SELECTION FUNCTIONS ********************* */ 00149 00150 #define HIDDEN 1 00151 #define VISIBLE 0 00152 00153 #define FIRST 1 00154 #define LAST 0 00155 00156 00157 /* returns 1 in case (de)selection was successful */ 00158 static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden) 00159 { 00160 if(bezt) { 00161 if((bezt->hide==0) || (hidden==1)) { 00162 if(selstatus==1) { /* selects */ 00163 bezt->f1 |= flag; 00164 bezt->f2 |= flag; 00165 bezt->f3 |= flag; 00166 return 1; 00167 } 00168 else { /* deselects */ 00169 bezt->f1 &= ~flag; 00170 bezt->f2 &= ~flag; 00171 bezt->f3 &= ~flag; 00172 return 1; 00173 } 00174 } 00175 } 00176 00177 return 0; 00178 } 00179 00180 /* returns 1 in case (de)selection was successful */ 00181 static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden) 00182 { 00183 if(bp) { 00184 if((bp->hide==0) || (hidden==1)) { 00185 if(selstatus==1) { 00186 bp->f1 |= flag; 00187 return 1; 00188 } 00189 else { 00190 bp->f1 &= ~flag; 00191 return 1; 00192 } 00193 } 00194 } 00195 00196 return 0; 00197 } 00198 00199 static short swap_selection_beztriple(BezTriple *bezt) 00200 { 00201 if(bezt->f2 & SELECT) 00202 return select_beztriple(bezt, DESELECT, 1, VISIBLE); 00203 else 00204 return select_beztriple(bezt, SELECT, 1, VISIBLE); 00205 } 00206 00207 static short swap_selection_bpoint(BPoint *bp) 00208 { 00209 if(bp->f1 & SELECT) 00210 return select_bpoint(bp, DESELECT, 1, VISIBLE); 00211 else 00212 return select_bpoint(bp, SELECT, 1, VISIBLE); 00213 } 00214 00215 int isNurbsel(Nurb *nu) 00216 { 00217 BezTriple *bezt; 00218 BPoint *bp; 00219 int a; 00220 00221 if(nu->type == CU_BEZIER) { 00222 bezt= nu->bezt; 00223 a= nu->pntsu; 00224 while(a--) { 00225 if( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) return 1; 00226 bezt++; 00227 } 00228 } 00229 else { 00230 bp= nu->bp; 00231 a= nu->pntsu*nu->pntsv; 00232 while(a--) { 00233 if( (bp->f1 & SELECT) ) return 1; 00234 bp++; 00235 } 00236 } 00237 return 0; 00238 } 00239 00240 static int isNurbsel_count(Curve *cu, Nurb *nu) 00241 { 00242 BezTriple *bezt; 00243 BPoint *bp; 00244 int a, sel=0; 00245 00246 if(nu->type == CU_BEZIER) { 00247 bezt= nu->bezt; 00248 a= nu->pntsu; 00249 while(a--) { 00250 if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) sel++; 00251 bezt++; 00252 } 00253 } 00254 else { 00255 bp= nu->bp; 00256 a= nu->pntsu*nu->pntsv; 00257 while(a--) { 00258 if( (bp->f1 & SELECT) ) sel++; 00259 bp++; 00260 } 00261 } 00262 return sel; 00263 } 00264 00265 /* ******************* PRINTS ********************* */ 00266 00267 void printknots(Object *obedit) 00268 { 00269 ListBase *editnurb= object_editcurve_get(obedit); 00270 Nurb *nu; 00271 int a, num; 00272 00273 for(nu= editnurb->first; nu; nu= nu->next) { 00274 if(isNurbsel(nu) && nu->type == CU_NURBS) { 00275 if(nu->knotsu) { 00276 num= KNOTSU(nu); 00277 for(a=0;a<num;a++) printf("knotu %d: %f\n", a, nu->knotsu[a]); 00278 } 00279 if(nu->knotsv) { 00280 num= KNOTSV(nu); 00281 for(a=0;a<num;a++) printf("knotv %d: %f\n", a, nu->knotsv[a]); 00282 } 00283 } 00284 } 00285 } 00286 00287 /* ********************* Shape keys *************** */ 00288 00289 static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, Nurb *orig_nu) 00290 { 00291 CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), "init_cvKeyIndex"); 00292 00293 cvIndex->orig_cv= cv; 00294 cvIndex->key_index= key_index; 00295 cvIndex->nu_index= nu_index; 00296 cvIndex->pt_index= pt_index; 00297 cvIndex->switched= 0; 00298 cvIndex->orig_nu= orig_nu; 00299 00300 return cvIndex; 00301 } 00302 00303 static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase) 00304 { 00305 Nurb *nu= editnurb->nurbs.first; 00306 Nurb *orignu= origBase->first; 00307 GHash *gh; 00308 BezTriple *bezt, *origbezt; 00309 BPoint *bp, *origbp; 00310 CVKeyIndex *keyIndex; 00311 int a, key_index= 0, nu_index= 0, pt_index= 0; 00312 00313 if(editnurb->keyindex) return; 00314 00315 gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "editNurb keyIndex"); 00316 00317 while (orignu) { 00318 if (orignu->bezt) { 00319 a= orignu->pntsu; 00320 bezt= nu->bezt; 00321 origbezt= orignu->bezt; 00322 pt_index= 0; 00323 while (a--) { 00324 keyIndex= init_cvKeyIndex(origbezt, key_index, nu_index, pt_index, orignu); 00325 BLI_ghash_insert(gh, bezt, keyIndex); 00326 key_index+= 12; 00327 bezt++; 00328 origbezt++; 00329 pt_index++; 00330 } 00331 } else { 00332 a= orignu->pntsu * orignu->pntsv; 00333 bp= nu->bp; 00334 origbp= orignu->bp; 00335 pt_index= 0; 00336 while (a--) { 00337 keyIndex= init_cvKeyIndex(origbp, key_index, nu_index, pt_index, orignu); 00338 BLI_ghash_insert(gh, bp, keyIndex); 00339 key_index+= 4; 00340 bp++; 00341 origbp++; 00342 pt_index++; 00343 } 00344 } 00345 00346 nu= nu->next; 00347 orignu= orignu->next; 00348 nu_index++; 00349 } 00350 00351 editnurb->keyindex= gh; 00352 } 00353 00354 static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv) 00355 { 00356 return BLI_ghash_lookup(editnurb->keyindex, cv); 00357 } 00358 00359 static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt) 00360 { 00361 CVKeyIndex *index= getCVKeyIndex(editnurb, bezt); 00362 00363 if (!index) { 00364 return NULL; 00365 } 00366 00367 return (BezTriple*)index->orig_cv; 00368 } 00369 00370 static BPoint *getKeyIndexOrig_bp(EditNurb *editnurb, BPoint *bp) 00371 { 00372 CVKeyIndex *index= getCVKeyIndex(editnurb, bp); 00373 00374 if (!index) { 00375 return NULL; 00376 } 00377 00378 return (BPoint*)index->orig_cv; 00379 } 00380 00381 static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv) 00382 { 00383 CVKeyIndex *index= getCVKeyIndex(editnurb, cv); 00384 00385 if (!index) { 00386 return -1; 00387 } 00388 00389 return index->key_index; 00390 } 00391 00392 static void keyIndex_delCV(EditNurb *editnurb, void *cv) 00393 { 00394 if (!editnurb->keyindex) { 00395 return; 00396 } 00397 00398 BLI_ghash_remove(editnurb->keyindex, cv, NULL, (GHashValFreeFP)MEM_freeN); 00399 } 00400 00401 static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt) 00402 { 00403 keyIndex_delCV(editnurb, bezt); 00404 } 00405 00406 static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp) 00407 { 00408 keyIndex_delCV(editnurb, bp); 00409 } 00410 00411 static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu) 00412 { 00413 int a; 00414 00415 if (!editnurb->keyindex) { 00416 return; 00417 } 00418 00419 if (nu->bezt) { 00420 BezTriple *bezt= nu->bezt; 00421 a= nu->pntsu; 00422 00423 while (a--) { 00424 BLI_ghash_remove(editnurb->keyindex, bezt, NULL, (GHashValFreeFP)MEM_freeN); 00425 ++bezt; 00426 } 00427 } else { 00428 BPoint *bp= nu->bp; 00429 a= nu->pntsu * nu->pntsv; 00430 00431 while (a--) { 00432 BLI_ghash_remove(editnurb->keyindex, bp, NULL, (GHashValFreeFP)MEM_freeN); 00433 ++bp; 00434 } 00435 } 00436 } 00437 00438 static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase) 00439 { 00440 Nurb *nu= nubase->first; 00441 00442 while (nu) { 00443 keyIndex_delNurb(editnurb, nu); 00444 00445 nu= nu->next; 00446 } 00447 } 00448 00449 static void keyIndex_updateCV(EditNurb *editnurb, char *cv, 00450 char *newcv, int count, int size) 00451 { 00452 int i; 00453 CVKeyIndex *index; 00454 00455 if (editnurb->keyindex == NULL) { 00456 /* No shape keys - updating not needed */ 00457 return; 00458 } 00459 00460 for (i = 0; i < count; i++) { 00461 index= getCVKeyIndex(editnurb, cv); 00462 00463 BLI_ghash_remove(editnurb->keyindex, cv, NULL, NULL); 00464 00465 if (index) { 00466 BLI_ghash_insert(editnurb->keyindex, newcv, index); 00467 } 00468 00469 newcv += size; 00470 cv += size; 00471 } 00472 } 00473 00474 static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt, 00475 BezTriple *newbezt, int count) 00476 { 00477 keyIndex_updateCV(editnurb, (char*)bezt, (char*)newbezt, count, sizeof(BezTriple)); 00478 } 00479 00480 static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp, 00481 BPoint *newbp, int count) 00482 { 00483 keyIndex_updateCV(editnurb, (char*)bp, (char*)newbp, count, sizeof(BPoint)); 00484 } 00485 00486 static void keyIndex_updateNurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu) 00487 { 00488 if (nu->bezt) { 00489 keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu); 00490 } else { 00491 keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv); 00492 } 00493 } 00494 00495 static void keyIndex_swap(EditNurb *editnurb, void *a, void *b) 00496 { 00497 CVKeyIndex *index1= getCVKeyIndex(editnurb, a); 00498 CVKeyIndex *index2= getCVKeyIndex(editnurb, b); 00499 00500 BLI_ghash_remove(editnurb->keyindex, a, NULL, NULL); 00501 BLI_ghash_remove(editnurb->keyindex, b, NULL, NULL); 00502 00503 if(index2) BLI_ghash_insert(editnurb->keyindex, a, index2); 00504 if(index1) BLI_ghash_insert(editnurb->keyindex, b, index1); 00505 } 00506 00507 static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu) 00508 { 00509 int a; 00510 CVKeyIndex *index1, *index2; 00511 00512 if (nu->bezt) { 00513 BezTriple *bezt1, *bezt2; 00514 00515 a= nu->pntsu; 00516 00517 bezt1= nu->bezt; 00518 bezt2= bezt1+(a-1); 00519 00520 if (a & 1) ++a; 00521 00522 a/=2; 00523 00524 while (a--) { 00525 index1= getCVKeyIndex(editnurb, bezt1); 00526 index2= getCVKeyIndex(editnurb, bezt2); 00527 00528 if(index1) index1->switched= !index1->switched; 00529 00530 if (bezt1 != bezt2) { 00531 keyIndex_swap(editnurb, bezt1, bezt2); 00532 00533 if(index2) index2->switched= !index2->switched; 00534 } 00535 00536 bezt1++; 00537 bezt2--; 00538 } 00539 } else { 00540 BPoint *bp1, *bp2; 00541 00542 if (nu->pntsv == 1) { 00543 a= nu->pntsu; 00544 bp1= nu->bp; 00545 bp2= bp1+(a-1); 00546 a/= 2; 00547 while(bp1!=bp2 && a>0) { 00548 index1= getCVKeyIndex(editnurb, bp1); 00549 index2= getCVKeyIndex(editnurb, bp2); 00550 00551 if(index1) index1->switched= !index1->switched; 00552 00553 if (bp1 != bp2) { 00554 if(index2) index2->switched= !index2->switched; 00555 00556 keyIndex_swap(editnurb, bp1, bp2); 00557 } 00558 00559 a--; 00560 bp1++; 00561 bp2--; 00562 } 00563 } else { 00564 int b; 00565 00566 for(b=0; b<nu->pntsv; b++) { 00567 00568 bp1= nu->bp+b*nu->pntsu; 00569 a= nu->pntsu; 00570 bp2= bp1+(a-1); 00571 a/= 2; 00572 00573 while(bp1!=bp2 && a>0) { 00574 index1= getCVKeyIndex(editnurb, bp1); 00575 index2= getCVKeyIndex(editnurb, bp2); 00576 00577 if(index1) index1->switched= !index1->switched; 00578 00579 if (bp1 != bp2) { 00580 if(index2) index2->switched= !index2->switched; 00581 00582 keyIndex_swap(editnurb, bp1, bp2); 00583 } 00584 00585 a--; 00586 bp1++; 00587 bp2--; 00588 } 00589 } 00590 00591 } 00592 } 00593 } 00594 00595 static void switch_keys_direction(Curve *cu, Nurb *actnu) 00596 { 00597 KeyBlock *currkey; 00598 EditNurb *editnurb= cu->editnurb; 00599 ListBase *nubase= &editnurb->nurbs; 00600 Nurb *nu; 00601 float *fp; 00602 int a; 00603 00604 currkey = cu->key->block.first; 00605 while(currkey) { 00606 fp= currkey->data; 00607 00608 nu= nubase->first; 00609 while (nu) { 00610 if (nu->bezt) { 00611 BezTriple *bezt= nu->bezt; 00612 a= nu->pntsu; 00613 if (nu == actnu) { 00614 while (a--) { 00615 if(getKeyIndexOrig_bezt(editnurb, bezt)) { 00616 swap_v3_v3(fp, fp + 6); 00617 *(fp+9) = -*(fp+9); 00618 fp += 12; 00619 } 00620 bezt++; 00621 } 00622 } else fp += a * 12; 00623 } else { 00624 BPoint *bp= nu->bp; 00625 a= nu->pntsu * nu->pntsv; 00626 if (nu == actnu) { 00627 while (a--) { 00628 if(getKeyIndexOrig_bp(editnurb, bp)) { 00629 *(fp+3) = -*(fp+3); 00630 fp += 4; 00631 } 00632 bp++; 00633 } 00634 } else fp += a * 4; 00635 } 00636 00637 nu= nu->next; 00638 } 00639 00640 currkey= currkey->next; 00641 } 00642 } 00643 00644 static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu) 00645 { 00646 EditNurb *editnurb= cu->editnurb; 00647 00648 if (!editnurb->keyindex) { 00649 /* no shape keys - nothing to do */ 00650 return; 00651 } 00652 00653 keyIndex_switchDirection(editnurb, nu); 00654 if(cu->key) 00655 switch_keys_direction(cu, nu); 00656 } 00657 00658 static GHash *dupli_keyIndexHash(GHash *keyindex) 00659 { 00660 GHash *gh; 00661 GHashIterator *hashIter; 00662 00663 gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "dupli_keyIndex gh"); 00664 00665 for(hashIter = BLI_ghashIterator_new(keyindex); 00666 !BLI_ghashIterator_isDone(hashIter); 00667 BLI_ghashIterator_step(hashIter)) { 00668 void *cv = BLI_ghashIterator_getKey(hashIter); 00669 CVKeyIndex *index = BLI_ghashIterator_getValue(hashIter); 00670 CVKeyIndex *newIndex = MEM_callocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index"); 00671 00672 memcpy(newIndex, index, sizeof(CVKeyIndex)); 00673 00674 BLI_ghash_insert(gh, cv, newIndex); 00675 } 00676 00677 BLI_ghashIterator_free(hashIter); 00678 00679 return gh; 00680 } 00681 00682 static void key_to_bezt(float *key, BezTriple *basebezt, BezTriple *bezt) 00683 { 00684 memcpy(bezt, basebezt, sizeof(BezTriple)); 00685 memcpy(bezt->vec, key, sizeof(float) * 9); 00686 bezt->alfa= key[9]; 00687 } 00688 00689 static void bezt_to_key(BezTriple *bezt, float *key) 00690 { 00691 memcpy(key, bezt->vec, sizeof(float) * 9); 00692 key[9] = bezt->alfa; 00693 } 00694 00695 static void calc_keyHandles(ListBase *nurb, float *key) 00696 { 00697 Nurb *nu; 00698 int a; 00699 float *fp= key; 00700 BezTriple *bezt; 00701 00702 nu= nurb->first; 00703 while (nu) { 00704 if (nu->bezt) { 00705 BezTriple *prevp, *nextp; 00706 BezTriple cur, prev, next; 00707 float *startfp, *prevfp, *nextfp; 00708 00709 bezt= nu->bezt; 00710 a= nu->pntsu; 00711 startfp= fp; 00712 00713 if(nu->flagu & CU_NURB_CYCLIC) { 00714 prevp= bezt+(a-1); 00715 prevfp= fp+(12 * (a-1)); 00716 } else { 00717 prevp= NULL; 00718 prevfp= NULL; 00719 } 00720 00721 nextp= bezt + 1; 00722 nextfp= fp + 12; 00723 00724 while (a--) { 00725 key_to_bezt(fp, bezt, &cur); 00726 00727 if (nextp) key_to_bezt(nextfp, nextp, &next); 00728 if (prevp) key_to_bezt(prevfp, prevp, &prev); 00729 00730 calchandleNurb(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0); 00731 bezt_to_key(&cur, fp); 00732 00733 prevp= bezt; 00734 prevfp= fp; 00735 if(a==1) { 00736 if(nu->flagu & CU_NURB_CYCLIC) { 00737 nextp= nu->bezt; 00738 nextfp= startfp; 00739 } else { 00740 nextp= NULL; 00741 nextfp= NULL; 00742 } 00743 } 00744 else { 00745 ++nextp; 00746 nextfp += 12; 00747 } 00748 00749 ++bezt; 00750 fp += 12; 00751 } 00752 } else { 00753 a= nu->pntsu * nu->pntsv; 00754 fp += a * 4; 00755 } 00756 00757 nu= nu->next; 00758 } 00759 } 00760 00761 static void calc_shapeKeys(Object *obedit) 00762 { 00763 Curve *cu= (Curve*)obedit->data; 00764 00765 /* are there keys? */ 00766 if(cu->key) { 00767 int a, i; 00768 EditNurb *editnurb= cu->editnurb; 00769 KeyBlock *currkey; 00770 KeyBlock *actkey= BLI_findlink(&cu->key->block, editnurb->shapenr-1); 00771 BezTriple *bezt, *oldbezt; 00772 BPoint *bp, *oldbp; 00773 Nurb *nu; 00774 int totvert= count_curveverts(&editnurb->nurbs); 00775 00776 float (*ofs)[3] = NULL; 00777 float *oldkey, *newkey, *ofp; 00778 00779 /* editing the base key should update others */ 00780 if(cu->key->type==KEY_RELATIVE) { 00781 int act_is_basis = 0; 00782 /* find if this key is a basis for any others */ 00783 for(currkey = cu->key->block.first; currkey; currkey= currkey->next) { 00784 if(editnurb->shapenr-1 == currkey->relative) { 00785 act_is_basis = 1; 00786 break; 00787 } 00788 } 00789 00790 if(act_is_basis) { /* active key is a base */ 00791 int totvec= 0; 00792 00793 /* Calculate needed memory to store offset */ 00794 nu= editnurb->nurbs.first; 00795 while(nu) { 00796 if (nu->bezt) { 00797 /* Three vects to store handles and one for alfa */ 00798 totvec+= nu->pntsu * 4; 00799 } else { 00800 totvec+= 2 * nu->pntsu * nu->pntsv; 00801 } 00802 00803 nu= nu->next; 00804 } 00805 00806 ofs= MEM_callocN(sizeof(float) * 3 * totvec, "currkey->data"); 00807 nu= editnurb->nurbs.first; 00808 i= 0; 00809 while(nu) { 00810 if(nu->bezt) { 00811 bezt= nu->bezt; 00812 a= nu->pntsu; 00813 while(a--) { 00814 oldbezt= getKeyIndexOrig_bezt(editnurb, bezt); 00815 00816 if (oldbezt) { 00817 int j; 00818 for (j= 0; j < 3; ++j) { 00819 sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]); 00820 i++; 00821 } 00822 ofs[i++][0]= bezt->alfa - oldbezt->alfa; 00823 } else { 00824 i += 4; 00825 } 00826 bezt++; 00827 } 00828 } 00829 else { 00830 bp= nu->bp; 00831 a= nu->pntsu*nu->pntsv; 00832 while(a--) { 00833 oldbp= getKeyIndexOrig_bp(editnurb, bp); 00834 if (oldbp) { 00835 sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec); 00836 ofs[i+1][0]= bp->alfa - oldbp->alfa; 00837 } 00838 i += 2; 00839 ++bp; 00840 } 00841 } 00842 00843 nu= nu->next; 00844 } 00845 } 00846 } 00847 00848 currkey = cu->key->block.first; 00849 while(currkey) { 00850 int apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr-1 == currkey->relative)); 00851 00852 float *fp= newkey= MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); 00853 ofp= oldkey = currkey->data; 00854 00855 nu= editnurb->nurbs.first; 00856 i = 0; 00857 while(nu) { 00858 if(currkey == actkey) { 00859 int restore= actkey != cu->key->refkey; 00860 00861 if(nu->bezt) { 00862 bezt= nu->bezt; 00863 a= nu->pntsu; 00864 while(a--) { 00865 int j; 00866 oldbezt= getKeyIndexOrig_bezt(editnurb, bezt); 00867 00868 for (j= 0; j < 3; ++j, ++i) { 00869 copy_v3_v3(fp, bezt->vec[j]); 00870 00871 if (restore && oldbezt) { 00872 copy_v3_v3(bezt->vec[j], oldbezt->vec[j]); 00873 } 00874 00875 fp+= 3; 00876 } 00877 fp[0]= bezt->alfa; 00878 00879 if(restore && oldbezt) { 00880 bezt->alfa= oldbezt->alfa; 00881 } 00882 00883 fp+= 3; ++i;/* alphas */ 00884 ++bezt; 00885 } 00886 } 00887 else { 00888 bp= nu->bp; 00889 a= nu->pntsu*nu->pntsv; 00890 while(a--) { 00891 oldbp= getKeyIndexOrig_bp(editnurb, bp); 00892 00893 copy_v3_v3(fp, bp->vec); 00894 00895 fp[3]= bp->alfa; 00896 00897 if(restore && oldbp) { 00898 copy_v3_v3(bp->vec, oldbp->vec); 00899 bp->alfa= oldbp->alfa; 00900 } 00901 00902 fp+= 4; 00903 ++bp; 00904 i+=2; 00905 } 00906 } 00907 } 00908 else { 00909 int index; 00910 float *curofp; 00911 00912 if(oldkey) { 00913 if(nu->bezt) { 00914 bezt= nu->bezt; 00915 a= nu->pntsu; 00916 00917 while(a--) { 00918 index= getKeyIndexOrig_keyIndex(editnurb, bezt); 00919 if (index >= 0) { 00920 int j; 00921 curofp= ofp + index; 00922 00923 for (j= 0; j < 3; ++j, ++i) { 00924 copy_v3_v3(fp, curofp); 00925 00926 if(apply_offset) { 00927 add_v3_v3(fp, ofs[i]); 00928 } 00929 00930 fp+= 3; curofp+= 3; 00931 } 00932 fp[0]= curofp[0]; 00933 00934 if(apply_offset) { 00935 /* apply alfa offsets */ 00936 add_v3_v3(fp, ofs[i]); 00937 ++i; 00938 } 00939 00940 fp+= 3; /* alphas */ 00941 } else { 00942 int j; 00943 for (j= 0; j < 3; ++j, ++i) { 00944 copy_v3_v3(fp, bezt->vec[j]); 00945 fp+= 3; 00946 } 00947 fp[0]= bezt->alfa; 00948 00949 fp+= 3; /* alphas */ 00950 } 00951 ++bezt; 00952 } 00953 } 00954 else { 00955 bp= nu->bp; 00956 a= nu->pntsu*nu->pntsv; 00957 while(a--) { 00958 index= getKeyIndexOrig_keyIndex(editnurb, bp); 00959 00960 if (index >= 0) { 00961 curofp= ofp + index; 00962 copy_v3_v3(fp, curofp); 00963 fp[3]= curofp[3]; 00964 00965 if(apply_offset) { 00966 add_v3_v3(fp, ofs[i]); 00967 fp[3]+=ofs[i+1][0]; 00968 } 00969 } else { 00970 copy_v3_v3(fp, bp->vec); 00971 fp[3]= bp->alfa; 00972 } 00973 00974 fp+= 4; 00975 ++bp; 00976 i+=2; 00977 } 00978 } 00979 } 00980 } 00981 00982 nu= nu->next; 00983 } 00984 00985 if (apply_offset) { 00986 /* handles could become malicious after offsets applying */ 00987 calc_keyHandles(&editnurb->nurbs, newkey); 00988 } 00989 00990 currkey->totelem= totvert; 00991 if(currkey->data) MEM_freeN(currkey->data); 00992 currkey->data = newkey; 00993 00994 currkey= currkey->next; 00995 } 00996 00997 if(ofs) MEM_freeN(ofs); 00998 } 00999 } 01000 01001 /* ********************* Amimation data *************** */ 01002 01003 static int curve_is_animated(Object *ob) 01004 { 01005 Curve *cu= (Curve*)ob->data; 01006 AnimData *ad= BKE_animdata_from_id(&cu->id); 01007 01008 return ad && (ad->action || ad->drivers.first); 01009 } 01010 01011 static void fcurve_path_rename(AnimData *ad, char *orig_rna_path, char *rna_path, ListBase *orig_curves, ListBase *curves) 01012 { 01013 FCurve *fcu, *nfcu, *nextfcu; 01014 int len= strlen(orig_rna_path); 01015 01016 fcu= orig_curves->first; 01017 while (fcu) { 01018 nextfcu= fcu->next; 01019 if(!strncmp(fcu->rna_path, orig_rna_path, len)) { 01020 char *spath, *suffix= fcu->rna_path + len; 01021 nfcu= copy_fcurve(fcu); 01022 spath= nfcu->rna_path; 01023 nfcu->rna_path= BLI_sprintfN("%s%s", rna_path, suffix); 01024 BLI_addtail(curves, nfcu); 01025 01026 if (fcu->grp) { 01027 action_groups_remove_channel(ad->action, fcu); 01028 action_groups_add_channel(ad->action, fcu->grp, nfcu); 01029 } 01030 else if (ad->action && &ad->action->curves == orig_curves) 01031 BLI_remlink(&ad->action->curves, fcu); 01032 else 01033 BLI_remlink(&ad->drivers, fcu); 01034 01035 free_fcurve(fcu); 01036 01037 MEM_freeN(spath); 01038 } 01039 fcu= nextfcu; 01040 } 01041 } 01042 01043 static void fcurve_remove(AnimData *ad, ListBase *orig_curves, FCurve *fcu) 01044 { 01045 if(orig_curves==&ad->drivers) BLI_remlink(&ad->drivers, fcu); 01046 else action_groups_remove_channel(ad->action, fcu); 01047 01048 free_fcurve(fcu); 01049 } 01050 01051 static void curve_rename_fcurves(Object *obedit, ListBase *orig_curves) 01052 { 01053 int nu_index= 0, a, pt_index; 01054 Curve *cu= (Curve*)obedit->data; 01055 EditNurb *editnurb= cu->editnurb; 01056 Nurb *nu= editnurb->nurbs.first; 01057 CVKeyIndex *keyIndex; 01058 char rna_path[64], orig_rna_path[64]; 01059 AnimData *ad= BKE_animdata_from_id(&cu->id); 01060 ListBase curves= {NULL, NULL}; 01061 FCurve *fcu, *next; 01062 01063 while(nu) { 01064 if(nu->bezt) { 01065 BezTriple *bezt= nu->bezt; 01066 a= nu->pntsu; 01067 pt_index= 0; 01068 01069 while (a--) { 01070 keyIndex= getCVKeyIndex(editnurb, bezt); 01071 if(keyIndex) { 01072 BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index); 01073 BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].bezier_points[%d]", keyIndex->nu_index, keyIndex->pt_index); 01074 01075 if(keyIndex->switched) { 01076 char handle_path[64], orig_handle_path[64]; 01077 BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); 01078 BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); 01079 fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); 01080 01081 BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); 01082 BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); 01083 fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); 01084 } 01085 01086 fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); 01087 01088 keyIndex->nu_index= nu_index; 01089 keyIndex->pt_index= pt_index; 01090 } 01091 01092 bezt++; 01093 pt_index++; 01094 } 01095 } else { 01096 BPoint *bp= nu->bp; 01097 a= nu->pntsu * nu->pntsv; 01098 pt_index= 0; 01099 01100 while (a--) { 01101 keyIndex= getCVKeyIndex(editnurb, bp); 01102 if(keyIndex) { 01103 BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); 01104 BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index); 01105 fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); 01106 01107 keyIndex->nu_index= nu_index; 01108 keyIndex->pt_index= pt_index; 01109 } 01110 01111 bp++; 01112 pt_index++; 01113 } 01114 } 01115 nu= nu->next; 01116 nu_index++; 01117 } 01118 01119 /* remove pathes for removed control points 01120 need this to make further step with copying non-cv related curves copying 01121 not touching cv's f-cruves */ 01122 for(fcu= orig_curves->first; fcu; fcu= next) { 01123 next= fcu->next; 01124 01125 if(!strncmp(fcu->rna_path, "splines", 7)) { 01126 char *ch= strchr(fcu->rna_path, '.'); 01127 01128 if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7))) 01129 fcurve_remove(ad, orig_curves, fcu); 01130 } 01131 } 01132 01133 nu_index= 0; 01134 nu= editnurb->nurbs.first; 01135 while(nu) { 01136 keyIndex= NULL; 01137 if(nu->pntsu) { 01138 if(nu->bezt) keyIndex= getCVKeyIndex(editnurb, &nu->bezt[0]); 01139 else keyIndex= getCVKeyIndex(editnurb, &nu->bp[0]); 01140 } 01141 01142 if(keyIndex) { 01143 BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); 01144 BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); 01145 fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); 01146 } 01147 01148 nu_index++; 01149 nu= nu->next; 01150 } 01151 01152 /* the remainders in orig_curves can be copied back (like follow path) */ 01153 /* (if it's not path to spline) */ 01154 for(fcu= orig_curves->first; fcu; fcu= next) { 01155 next= fcu->next; 01156 01157 if(!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(ad, orig_curves, fcu); 01158 else BLI_addtail(&curves, fcu); 01159 } 01160 01161 *orig_curves= curves; 01162 } 01163 01164 /* return 0 if animation data wasn't changed, 1 otherwise */ 01165 int ED_curve_updateAnimPaths(Object *obedit) 01166 { 01167 Curve *cu= (Curve*)obedit->data; 01168 AnimData *ad= BKE_animdata_from_id(&cu->id); 01169 01170 if(!curve_is_animated(obedit)) return 0; 01171 01172 if(ad->action) 01173 curve_rename_fcurves(obedit, &ad->action->curves); 01174 01175 curve_rename_fcurves(obedit, &ad->drivers); 01176 01177 return 1; 01178 } 01179 01180 /* ********************* LOAD and MAKE *************** */ 01181 01182 /* load editNurb in object */ 01183 void load_editNurb(Object *obedit) 01184 { 01185 ListBase *editnurb= object_editcurve_get(obedit); 01186 01187 if(obedit==NULL) return; 01188 01189 set_actNurb(obedit, NULL); 01190 01191 if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { 01192 Curve *cu= obedit->data; 01193 Nurb *nu, *newnu; 01194 ListBase newnurb= {NULL, NULL}, oldnurb= cu->nurb; 01195 01196 for(nu= editnurb->first; nu; nu= nu->next) { 01197 newnu= duplicateNurb(nu); 01198 BLI_addtail(&newnurb, newnu); 01199 01200 if(nu->type == CU_NURBS) { 01201 clamp_nurb_order_u(nu); 01202 } 01203 } 01204 01205 cu->nurb= newnurb; 01206 01207 calc_shapeKeys(obedit); 01208 ED_curve_updateAnimPaths(obedit); 01209 01210 freeNurblist(&oldnurb); 01211 } 01212 01213 set_actNurb(obedit, NULL); 01214 } 01215 01216 /* make copy in cu->editnurb */ 01217 void make_editNurb(Object *obedit) 01218 { 01219 Curve *cu= (Curve*)obedit->data; 01220 EditNurb *editnurb= cu->editnurb; 01221 Nurb *nu, *newnu, *nu_act= NULL; 01222 KeyBlock *actkey; 01223 01224 01225 set_actNurb(obedit, NULL); 01226 01227 if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { 01228 actkey= ob_get_keyblock(obedit); 01229 01230 if(actkey) { 01231 // XXX strcpy(G.editModeTitleExtra, "(Key) "); 01232 undo_editmode_clear(); 01233 key_to_curve(actkey, cu, &cu->nurb); 01234 } 01235 01236 if(editnurb) { 01237 freeNurblist(&editnurb->nurbs); 01238 free_curve_editNurb_keyIndex(editnurb); 01239 editnurb->keyindex= NULL; 01240 } else { 01241 editnurb= MEM_callocN(sizeof(EditNurb), "editnurb"); 01242 cu->editnurb= editnurb; 01243 } 01244 01245 nu= cu->nurb.first; 01246 cu->lastsel= NULL; /* for select row */ 01247 01248 while(nu) { 01249 newnu= duplicateNurb(nu); 01250 test2DNurb(newnu); // after join, or any other creation of curve 01251 BLI_addtail(&editnurb->nurbs, newnu); 01252 01253 if (nu_act == NULL && isNurbsel(nu)) { 01254 nu_act= newnu; 01255 set_actNurb(obedit, newnu); 01256 } 01257 01258 nu= nu->next; 01259 } 01260 01261 if(actkey) 01262 editnurb->shapenr= obedit->shapenr; 01263 01264 /* animation could be added in editmode even if teher was no animdata i 01265 object mode hence we always need CVs index be created */ 01266 init_editNurb_keyIndex(editnurb, &cu->nurb); 01267 } 01268 } 01269 01270 void free_editNurb(Object *obedit) 01271 { 01272 Curve *cu= obedit->data; 01273 01274 free_curve_editNurb(cu); 01275 } 01276 01277 void CU_deselect_all(Object *obedit) 01278 { 01279 ListBase *editnurb= object_editcurve_get(obedit); 01280 01281 if (editnurb) { 01282 selectend_nurb(obedit, FIRST, 0, DESELECT); /* set first control points as unselected */ 01283 select_adjacent_cp(editnurb, 1, 1, DESELECT); /* cascade selection */ 01284 } 01285 } 01286 01287 void CU_select_all(Object *obedit) 01288 { 01289 ListBase *editnurb= object_editcurve_get(obedit); 01290 01291 if (editnurb) { 01292 selectend_nurb(obedit, FIRST, 0, SELECT); /* set first control points as unselected */ 01293 select_adjacent_cp(editnurb, 1, 1, SELECT); /* cascade selection */ 01294 } 01295 } 01296 01297 void CU_select_swap(Object *obedit) 01298 { 01299 ListBase *editnurb= object_editcurve_get(obedit); 01300 01301 if (editnurb) { 01302 Curve *cu= obedit->data; 01303 Nurb *nu; 01304 BPoint *bp; 01305 BezTriple *bezt; 01306 int a; 01307 01308 cu->lastsel= NULL; 01309 01310 for(nu= editnurb->first; nu; nu= nu->next) { 01311 if(nu->type == CU_BEZIER) { 01312 bezt= nu->bezt; 01313 a= nu->pntsu; 01314 while(a--) { 01315 if(bezt->hide==0) { 01316 bezt->f2 ^= SELECT; /* always do the center point */ 01317 if((cu->drawflag & CU_HIDE_HANDLES)==0) { 01318 bezt->f1 ^= SELECT; 01319 bezt->f3 ^= SELECT; 01320 } 01321 } 01322 bezt++; 01323 } 01324 } 01325 else { 01326 bp= nu->bp; 01327 a= nu->pntsu*nu->pntsv; 01328 while(a--) { 01329 swap_selection_bpoint(bp); 01330 bp++; 01331 } 01332 } 01333 } 01334 } 01335 } 01336 01337 /******************** separate operator ***********************/ 01338 01339 static int separate_exec(bContext *C, wmOperator *op) 01340 { 01341 Main *bmain= CTX_data_main(C); 01342 Scene *scene= CTX_data_scene(C); 01343 Nurb *nu, *nu1; 01344 Object *oldob, *newob; 01345 Base *oldbase, *newbase; 01346 Curve *oldcu, *newcu; 01347 EditNurb *oldedit, *newedit; 01348 01349 oldbase= CTX_data_active_base(C); 01350 oldob= oldbase->object; 01351 oldcu= oldob->data; 01352 oldedit= oldcu->editnurb; 01353 01354 if(oldcu->key) { 01355 BKE_report(op->reports, RPT_ERROR, "Can't separate a curve with vertex keys"); 01356 return OPERATOR_CANCELLED; 01357 } 01358 01359 WM_cursor_wait(1); 01360 01361 /* 1. duplicate the object and data */ 01362 newbase= ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */ 01363 ED_base_object_select(newbase, BA_DESELECT); 01364 newob= newbase->object; 01365 01366 newcu= newob->data= copy_curve(oldcu); 01367 newcu->editnurb= NULL; 01368 oldcu->id.us--; /* because new curve is a copy: reduce user count */ 01369 01370 /* 2. put new object in editmode and clear it */ 01371 make_editNurb(newob); 01372 newedit= newcu->editnurb; 01373 freeNurblist(&newedit->nurbs); 01374 free_curve_editNurb_keyIndex(newedit); 01375 01376 /* 3. move over parts from old object */ 01377 for(nu= oldedit->nurbs.first; nu; nu=nu1) { 01378 nu1= nu->next; 01379 01380 if(isNurbsel(nu)) { 01381 BLI_remlink(&oldedit->nurbs, nu); 01382 BLI_addtail(&newedit->nurbs, nu); 01383 } 01384 } 01385 01386 /* 4. put old object out of editmode */ 01387 load_editNurb(newob); 01388 free_editNurb(newob); 01389 01390 DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */ 01391 DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */ 01392 01393 WM_event_add_notifier(C, NC_GEOM|ND_DATA, oldob->data); 01394 01395 WM_cursor_wait(0); 01396 01397 return OPERATOR_FINISHED; 01398 } 01399 01400 void CURVE_OT_separate(wmOperatorType *ot) 01401 { 01402 /* identifiers */ 01403 ot->name= "Separate"; 01404 ot->idname= "CURVE_OT_separate"; 01405 01406 /* api callbacks */ 01407 ot->exec= separate_exec; 01408 ot->poll= ED_operator_editsurfcurve; 01409 01410 /* flags */ 01411 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01412 } 01413 01414 /* ******************* FLAGS ********************* */ 01415 01416 static short isNurbselUV(Nurb *nu, int *u, int *v, int flag) 01417 { 01418 /* return u!=-1: 1 row in u-direction selected. U has value between 0-pntsv 01419 * return v!=-1: 1 collumn in v-direction selected. V has value between 0-pntsu 01420 */ 01421 BPoint *bp; 01422 int a, b, sel; 01423 01424 *u= *v= -1; 01425 01426 bp= nu->bp; 01427 for(b=0; b<nu->pntsv; b++) { 01428 sel= 0; 01429 for(a=0; a<nu->pntsu; a++, bp++) { 01430 if(bp->f1 & flag) sel++; 01431 } 01432 if(sel==nu->pntsu) { 01433 if(*u== -1) *u= b; 01434 else return 0; 01435 } 01436 else if(sel>1) return 0; /* because sel==1 is still ok */ 01437 } 01438 01439 for(a=0; a<nu->pntsu; a++) { 01440 sel= 0; 01441 bp= nu->bp+a; 01442 for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) { 01443 if(bp->f1 & flag) sel++; 01444 } 01445 if(sel==nu->pntsv) { 01446 if(*v== -1) *v= a; 01447 else return 0; 01448 } 01449 else if(sel>1) return 0; 01450 } 01451 01452 if(*u==-1 && *v>-1) return 1; 01453 if(*v==-1 && *u>-1) return 1; 01454 return 0; 01455 } 01456 01457 static void setflagsNurb(ListBase *editnurb, short flag) 01458 { 01459 Nurb *nu; 01460 BezTriple *bezt; 01461 BPoint *bp; 01462 int a; 01463 01464 for(nu= editnurb->first; nu; nu= nu->next) { 01465 if(nu->type == CU_BEZIER) { 01466 a= nu->pntsu; 01467 bezt= nu->bezt; 01468 while(a--) { 01469 bezt->f1= bezt->f2= bezt->f3= flag; 01470 bezt++; 01471 } 01472 } 01473 else { 01474 a= nu->pntsu*nu->pntsv; 01475 bp= nu->bp; 01476 while(a--) { 01477 bp->f1= flag; 01478 bp++; 01479 } 01480 } 01481 } 01482 } 01483 01484 static void rotateflagNurb(ListBase *editnurb, short flag, float *cent, float rotmat[][3]) 01485 { 01486 /* all verts with (flag & 'flag') rotate */ 01487 Nurb *nu; 01488 BPoint *bp; 01489 int a; 01490 01491 for(nu= editnurb->first; nu; nu= nu->next) { 01492 if(nu->type == CU_NURBS) { 01493 bp= nu->bp; 01494 a= nu->pntsu*nu->pntsv; 01495 01496 while(a--) { 01497 if(bp->f1 & flag) { 01498 sub_v3_v3(bp->vec, cent); 01499 mul_m3_v3(rotmat, bp->vec); 01500 add_v3_v3(bp->vec, cent); 01501 } 01502 bp++; 01503 } 01504 } 01505 } 01506 } 01507 01508 static void translateflagNurb(ListBase *editnurb, short flag, float *vec) 01509 { 01510 /* all verts with ('flag' & flag) translate */ 01511 Nurb *nu; 01512 BezTriple *bezt; 01513 BPoint *bp; 01514 int a; 01515 01516 for(nu= editnurb->first; nu; nu= nu->next) { 01517 if(nu->type == CU_BEZIER) { 01518 a= nu->pntsu; 01519 bezt= nu->bezt; 01520 while(a--) { 01521 if(bezt->f1 & flag) add_v3_v3(bezt->vec[0], vec); 01522 if(bezt->f2 & flag) add_v3_v3(bezt->vec[1], vec); 01523 if(bezt->f3 & flag) add_v3_v3(bezt->vec[2], vec); 01524 bezt++; 01525 } 01526 } 01527 else { 01528 a= nu->pntsu*nu->pntsv; 01529 bp= nu->bp; 01530 while(a--) { 01531 if(bp->f1 & flag) add_v3_v3(bp->vec, vec); 01532 bp++; 01533 } 01534 } 01535 01536 test2DNurb(nu); 01537 } 01538 } 01539 01540 static void weightflagNurb(ListBase *editnurb, short flag, float w) 01541 { 01542 Nurb *nu; 01543 BPoint *bp; 01544 int a; 01545 01546 for(nu= editnurb->first; nu; nu= nu->next) { 01547 if(nu->type == CU_NURBS) { 01548 a= nu->pntsu*nu->pntsv; 01549 bp= nu->bp; 01550 while(a--) { 01551 if(bp->f1 & flag) { 01552 /* a mode used to exist for replace/multiple but is was unused */ 01553 bp->vec[3]*= w; 01554 } 01555 bp++; 01556 } 01557 } 01558 } 01559 } 01560 01561 static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) 01562 { 01563 Object *obedit= CTX_data_edit_object(C); 01564 Curve *cu= obedit->data; 01565 ListBase *editnurb= object_editcurve_get(obedit); 01566 Nurb *nu, *next; 01567 BPoint *bp, *bpn, *newbp; 01568 int a, b, newu, newv, sel; 01569 01570 if(obedit->type==OB_SURF); 01571 else return OPERATOR_CANCELLED; 01572 01573 cu->lastsel= NULL; 01574 01575 nu= editnurb->first; 01576 while(nu) { 01577 next= nu->next; 01578 01579 /* is entire nurb selected */ 01580 bp= nu->bp; 01581 a= nu->pntsu*nu->pntsv; 01582 while(a) { 01583 a--; 01584 if(bp->f1 & flag); 01585 else break; 01586 bp++; 01587 } 01588 if(a==0) { 01589 BLI_remlink(editnurb, nu); 01590 keyIndex_delNurb(cu->editnurb, nu); 01591 freeNurb(nu); nu=NULL; 01592 } 01593 else { 01594 /* is nurb in U direction selected */ 01595 newv= nu->pntsv; 01596 bp= nu->bp; 01597 for(b=0; b<nu->pntsv; b++) { 01598 sel= 0; 01599 for(a=0; a<nu->pntsu; a++, bp++) { 01600 if(bp->f1 & flag) sel++; 01601 } 01602 if(sel==nu->pntsu) { 01603 newv--; 01604 } 01605 else if(sel>=1) { 01606 /* don't delete */ 01607 break; 01608 } 01609 } 01610 if(newv!=nu->pntsv && b==nu->pntsv) { 01611 /* delete */ 01612 bp= nu->bp; 01613 bpn = newbp = 01614 (BPoint*) MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb"); 01615 for(b=0; b<nu->pntsv; b++) { 01616 if((bp->f1 & flag)==0) { 01617 memcpy(bpn, bp, nu->pntsu*sizeof(BPoint)); 01618 keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu); 01619 bpn+= nu->pntsu; 01620 } else { 01621 keyIndex_delBP(cu->editnurb, bp); 01622 } 01623 bp+= nu->pntsu; 01624 } 01625 nu->pntsv= newv; 01626 MEM_freeN(nu->bp); 01627 nu->bp= newbp; 01628 clamp_nurb_order_v(nu); 01629 01630 nurbs_knot_calc_v(nu); 01631 } 01632 else { 01633 /* is the nurb in V direction selected */ 01634 newu= nu->pntsu; 01635 for(a=0; a<nu->pntsu; a++) { 01636 bp= nu->bp+a; 01637 sel= 0; 01638 for(b=0; b<nu->pntsv; b++, bp+=nu->pntsu) { 01639 if(bp->f1 & flag) sel++; 01640 } 01641 if(sel==nu->pntsv) { 01642 newu--; 01643 } 01644 else if(sel>=1) { 01645 /* don't delete */ 01646 break; 01647 } 01648 } 01649 if(newu!=nu->pntsu && a==nu->pntsu) { 01650 /* delete */ 01651 bp= nu->bp; 01652 bpn = newbp = 01653 (BPoint*) MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb"); 01654 for(b=0; b<nu->pntsv; b++) { 01655 for(a=0; a<nu->pntsu; a++, bp++) { 01656 if((bp->f1 & flag)==0) { 01657 *bpn= *bp; 01658 keyIndex_updateBP(cu->editnurb, bp, bpn, 1); 01659 bpn++; 01660 } else { 01661 keyIndex_delBP(cu->editnurb, bp); 01662 } 01663 } 01664 } 01665 MEM_freeN(nu->bp); 01666 nu->bp= newbp; 01667 if(newu==1 && nu->pntsv>1) { /* make a U spline */ 01668 nu->pntsu= nu->pntsv; 01669 nu->pntsv= 1; 01670 SWAP(short, nu->orderu, nu->orderv); 01671 clamp_nurb_order_u(nu); 01672 if(nu->knotsv) MEM_freeN(nu->knotsv); 01673 nu->knotsv= NULL; 01674 } 01675 else { 01676 nu->pntsu= newu; 01677 clamp_nurb_order_u(nu); 01678 } 01679 nurbs_knot_calc_u(nu); 01680 } 01681 } 01682 } 01683 nu= next; 01684 } 01685 01686 if(ED_curve_updateAnimPaths(obedit)) 01687 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 01688 01689 return OPERATOR_FINISHED; 01690 } 01691 01692 /* only for OB_SURF */ 01693 static short extrudeflagNurb(EditNurb *editnurb, int flag) 01694 { 01695 Nurb *nu; 01696 BPoint *bp, *bpn, *newbp; 01697 int ok= 0, a, u, v, len; 01698 01699 nu= editnurb->nurbs.first; 01700 while(nu) { 01701 01702 if(nu->pntsv==1) { 01703 bp= nu->bp; 01704 a= nu->pntsu; 01705 while(a) { 01706 if(bp->f1 & flag); 01707 else break; 01708 bp++; 01709 a--; 01710 } 01711 if(a==0) { 01712 ok= 1; 01713 newbp = 01714 (BPoint*)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1"); 01715 ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); 01716 bp= newbp+ nu->pntsu; 01717 ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu); 01718 MEM_freeN(nu->bp); 01719 nu->bp= newbp; 01720 a= nu->pntsu; 01721 while(a--) { 01722 select_bpoint(bp, SELECT, flag, HIDDEN); 01723 select_bpoint(newbp, DESELECT, flag, HIDDEN); 01724 bp++; 01725 newbp++; 01726 } 01727 01728 nu->pntsv= 2; 01729 nu->orderv= 2; 01730 nurbs_knot_calc_v(nu); 01731 } 01732 } 01733 else { 01734 /* which row or column is selected */ 01735 01736 if( isNurbselUV(nu, &u, &v, flag) ) { 01737 01738 /* deselect all */ 01739 bp= nu->bp; 01740 a= nu->pntsu*nu->pntsv; 01741 while(a--) { 01742 select_bpoint(bp, DESELECT, flag, HIDDEN); 01743 bp++; 01744 } 01745 01746 if(u==0 || u== nu->pntsv-1) { /* row in u-direction selected */ 01747 ok= 1; 01748 newbp = 01749 (BPoint*) MEM_mallocN(nu->pntsu*(nu->pntsv + 1) 01750 * sizeof(BPoint), "extrudeNurb1"); 01751 if(u==0) { 01752 len= nu->pntsv*nu->pntsu; 01753 ED_curve_bpcpy(editnurb, newbp+nu->pntsu, nu->bp, len); 01754 ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); 01755 bp= newbp; 01756 } 01757 else { 01758 len= nu->pntsv*nu->pntsu; 01759 ED_curve_bpcpy(editnurb, newbp, nu->bp, len); 01760 ED_curve_bpcpy(editnurb, newbp+len, nu->bp+len-nu->pntsu, nu->pntsu); 01761 bp= newbp+len; 01762 } 01763 01764 a= nu->pntsu; 01765 while(a--) { 01766 select_bpoint(bp, SELECT, flag, HIDDEN); 01767 bp++; 01768 } 01769 01770 MEM_freeN(nu->bp); 01771 nu->bp= newbp; 01772 nu->pntsv++; 01773 nurbs_knot_calc_v(nu); 01774 } 01775 else if(v==0 || v== nu->pntsu-1) { /* collumn in v-direction selected */ 01776 ok= 1; 01777 bpn = newbp = 01778 (BPoint*) MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1"); 01779 bp= nu->bp; 01780 01781 for(a=0; a<nu->pntsv; a++) { 01782 if(v==0) { 01783 *bpn= *bp; 01784 bpn->f1 |= flag; 01785 bpn++; 01786 } 01787 ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu); 01788 bp+= nu->pntsu; 01789 bpn+= nu->pntsu; 01790 if(v== nu->pntsu-1) { 01791 *bpn= *(bp-1); 01792 bpn->f1 |= flag; 01793 bpn++; 01794 } 01795 } 01796 01797 MEM_freeN(nu->bp); 01798 nu->bp= newbp; 01799 nu->pntsu++; 01800 nurbs_knot_calc_u(nu); 01801 } 01802 } 01803 } 01804 nu= nu->next; 01805 } 01806 01807 return ok; 01808 } 01809 01810 static void adduplicateflagNurb(Object *obedit, short flag) 01811 { 01812 ListBase *editnurb= object_editcurve_get(obedit); 01813 Nurb *nu, *newnu; 01814 BezTriple *bezt, *bezt1; 01815 BPoint *bp, *bp1; 01816 Curve *cu= (Curve*)obedit->data; 01817 int a, b, starta, enda, newu, newv; 01818 char *usel; 01819 01820 cu->lastsel= NULL; 01821 01822 nu= editnurb->last; 01823 while(nu) { 01824 if(nu->type == CU_BEZIER) { 01825 bezt= nu->bezt; 01826 for(a=0; a<nu->pntsu; a++) { 01827 enda= -1; 01828 starta= a; 01829 while( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) { 01830 select_beztriple(bezt, DESELECT, flag, HIDDEN); 01831 enda=a; 01832 if(a>=nu->pntsu-1) break; 01833 a++; 01834 bezt++; 01835 } 01836 if(enda>=starta) { 01837 newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN"); 01838 memcpy(newnu, nu, sizeof(Nurb)); 01839 BLI_addtail(editnurb, newnu); 01840 set_actNurb(obedit, newnu); 01841 newnu->pntsu= enda-starta+1; 01842 newnu->bezt= 01843 (BezTriple*)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN"); 01844 memcpy(newnu->bezt, nu->bezt+starta, newnu->pntsu*sizeof(BezTriple)); 01845 01846 b= newnu->pntsu; 01847 bezt1= newnu->bezt; 01848 while(b--) { 01849 select_beztriple(bezt1, SELECT, flag, HIDDEN); 01850 bezt1++; 01851 } 01852 01853 if(nu->flagu & CU_NURB_CYCLIC) { 01854 if(starta!=0 || enda!=nu->pntsu-1) { 01855 newnu->flagu &= ~CU_NURB_CYCLIC; 01856 } 01857 } 01858 } 01859 bezt++; 01860 } 01861 } 01862 else if(nu->pntsv==1) { /* because UV Nurb has a different method for dupli */ 01863 bp= nu->bp; 01864 for(a=0; a<nu->pntsu; a++) { 01865 enda= -1; 01866 starta= a; 01867 while(bp->f1 & flag) { 01868 select_bpoint(bp, DESELECT, flag, HIDDEN); 01869 enda= a; 01870 if(a>=nu->pntsu-1) break; 01871 a++; 01872 bp++; 01873 } 01874 if(enda>=starta) { 01875 newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN3"); 01876 memcpy(newnu, nu, sizeof(Nurb)); 01877 set_actNurb(obedit, newnu); 01878 BLI_addtail(editnurb, newnu); 01879 newnu->pntsu= enda-starta+1; 01880 newnu->bp = (BPoint*)MEM_mallocN((enda-starta+1) * sizeof(BPoint), "adduplicateN4"); 01881 memcpy(newnu->bp, nu->bp+starta, newnu->pntsu*sizeof(BPoint)); 01882 01883 b= newnu->pntsu; 01884 bp1= newnu->bp; 01885 while(b--) { 01886 select_bpoint(bp1, SELECT, flag, HIDDEN); 01887 bp1++; 01888 } 01889 01890 if(nu->flagu & CU_NURB_CYCLIC) { 01891 if(starta!=0 || enda!=nu->pntsu-1) { 01892 newnu->flagu &= ~CU_NURB_CYCLIC; 01893 } 01894 } 01895 01896 /* knots */ 01897 newnu->knotsu= NULL; 01898 nurbs_knot_calc_u(newnu); 01899 } 01900 bp++; 01901 } 01902 } 01903 else { 01904 /* a rectangular area in nurb has to be selected */ 01905 if(isNurbsel(nu)) { 01906 usel= MEM_callocN(nu->pntsu, "adduplicateN4"); 01907 bp= nu->bp; 01908 for(a=0; a<nu->pntsv; a++) { 01909 for(b=0; b<nu->pntsu; b++, bp++) { 01910 if(bp->f1 & flag) usel[b]++; 01911 } 01912 } 01913 newu= 0; 01914 newv= 0; 01915 for(a=0; a<nu->pntsu; a++) { 01916 if(usel[a]) { 01917 if(newv==0 || usel[a]==newv) { 01918 newv= usel[a]; 01919 newu++; 01920 } 01921 else { 01922 newv= 0; 01923 break; 01924 } 01925 } 01926 } 01927 if(newu==0 || newv==0) { 01928 if (G.f & G_DEBUG) 01929 printf("Can't duplicate Nurb\n"); 01930 } 01931 else { 01932 01933 if(newu==1) SWAP(short, newu, newv); 01934 01935 newnu = (Nurb*)MEM_mallocN(sizeof(Nurb), "adduplicateN5"); 01936 memcpy(newnu, nu, sizeof(Nurb)); 01937 BLI_addtail(editnurb, newnu); 01938 set_actNurb(obedit, newnu); 01939 newnu->pntsu= newu; 01940 newnu->pntsv= newv; 01941 newnu->bp = 01942 (BPoint*)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6"); 01943 clamp_nurb_order_u(newnu); 01944 clamp_nurb_order_v(newnu); 01945 01946 newnu->knotsu= newnu->knotsv= NULL; 01947 01948 bp= newnu->bp; 01949 bp1= nu->bp; 01950 for(a=0; a<nu->pntsv; a++) { 01951 for(b=0; b<nu->pntsu; b++, bp1++) { 01952 if(bp1->f1 & flag) { 01953 memcpy(bp, bp1, sizeof(BPoint)); 01954 select_bpoint(bp1, DESELECT, flag, HIDDEN); 01955 bp++; 01956 } 01957 } 01958 } 01959 if (check_valid_nurb_u(newnu)) { 01960 if(nu->pntsu==newnu->pntsu && nu->knotsu) { 01961 newnu->knotsu= MEM_dupallocN( nu->knotsu ); 01962 } else { 01963 nurbs_knot_calc_u(newnu); 01964 } 01965 } 01966 if (check_valid_nurb_v(newnu)) { 01967 if(nu->pntsv==newnu->pntsv && nu->knotsv) { 01968 newnu->knotsv= MEM_dupallocN( nu->knotsv ); 01969 } else { 01970 nurbs_knot_calc_v(newnu); 01971 } 01972 } 01973 } 01974 MEM_freeN(usel); 01975 } 01976 } 01977 01978 nu= nu->prev; 01979 } 01980 01981 /* actnu changed */ 01982 } 01983 01984 /**************** switch direction operator ***************/ 01985 01986 static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) 01987 { 01988 Object *obedit= CTX_data_edit_object(C); 01989 Curve *cu= (Curve*)obedit->data; 01990 EditNurb *editnurb= cu->editnurb; 01991 Nurb *nu; 01992 01993 for(nu= editnurb->nurbs.first; nu; nu= nu->next) 01994 if(isNurbsel(nu)) { 01995 switchdirectionNurb(nu); 01996 keyData_switchDirectionNurb(cu, nu); 01997 } 01998 01999 if(ED_curve_updateAnimPaths(obedit)) 02000 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 02001 02002 DAG_id_tag_update(obedit->data, 0); 02003 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02004 02005 return OPERATOR_FINISHED; 02006 } 02007 02008 void CURVE_OT_switch_direction(wmOperatorType *ot) 02009 { 02010 /* identifiers */ 02011 ot->name= "Switch Direction"; 02012 ot->description= "Switch direction of selected splines"; 02013 ot->idname= "CURVE_OT_switch_direction"; 02014 02015 /* api callbacks */ 02016 ot->exec= switch_direction_exec; 02017 ot->poll= ED_operator_editsurfcurve; 02018 02019 /* flags */ 02020 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02021 } 02022 02023 /****************** set weight operator *******************/ 02024 02025 static int set_goal_weight_exec(bContext *C, wmOperator *op) 02026 { 02027 Object *obedit= CTX_data_edit_object(C); 02028 ListBase *editnurb= object_editcurve_get(obedit); 02029 Nurb *nu; 02030 BezTriple *bezt; 02031 BPoint *bp; 02032 float weight= RNA_float_get(op->ptr, "weight"); 02033 int a; 02034 02035 for(nu= editnurb->first; nu; nu= nu->next) { 02036 if(nu->bezt) { 02037 for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) { 02038 if(bezt->f2 & SELECT) 02039 bezt->weight= weight; 02040 } 02041 } 02042 else if(nu->bp) { 02043 for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) { 02044 if(bp->f1 & SELECT) 02045 bp->weight= weight; 02046 } 02047 } 02048 } 02049 02050 DAG_id_tag_update(obedit->data, 0); 02051 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02052 02053 return OPERATOR_FINISHED; 02054 } 02055 02056 void CURVE_OT_spline_weight_set(wmOperatorType *ot) 02057 { 02058 /* identifiers */ 02059 ot->name= "Set Goal Weight"; 02060 ot->description= "Set softbody goal weight for selected points"; 02061 ot->idname= "CURVE_OT_spline_weight_set"; 02062 02063 /* api callbacks */ 02064 ot->exec= set_goal_weight_exec; 02065 ot->invoke= WM_operator_props_popup; 02066 ot->poll= ED_operator_editsurfcurve; 02067 02068 /* flags */ 02069 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02070 02071 /* properties */ 02072 RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); 02073 } 02074 02075 /******************* set radius operator ******************/ 02076 02077 static int set_radius_exec(bContext *C, wmOperator *op) 02078 { 02079 Object *obedit= CTX_data_edit_object(C); 02080 ListBase *editnurb= object_editcurve_get(obedit); 02081 Nurb *nu; 02082 BezTriple *bezt; 02083 BPoint *bp; 02084 float radius= RNA_float_get(op->ptr, "radius"); 02085 int a; 02086 02087 for(nu= editnurb->first; nu; nu= nu->next) { 02088 if(nu->bezt) { 02089 for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) { 02090 if(bezt->f2 & SELECT) 02091 bezt->radius= radius; 02092 } 02093 } 02094 else if(nu->bp) { 02095 for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) { 02096 if(bp->f1 & SELECT) 02097 bp->radius= radius; 02098 } 02099 } 02100 } 02101 02102 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02103 DAG_id_tag_update(obedit->data, 0); 02104 02105 return OPERATOR_FINISHED; 02106 } 02107 02108 void CURVE_OT_radius_set(wmOperatorType *ot) 02109 { 02110 /* identifiers */ 02111 ot->name= "Set Curve Radius"; 02112 ot->description= "Set per-point radius which is used for bevel tapering"; 02113 ot->idname= "CURVE_OT_radius_set"; 02114 02115 /* api callbacks */ 02116 ot->exec= set_radius_exec; 02117 ot->invoke= WM_operator_props_popup; 02118 ot->poll= ED_operator_editsurfcurve; 02119 02120 /* flags */ 02121 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02122 02123 /* properties */ 02124 RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "", 0.0001f, 10.0f); 02125 } 02126 02127 /********************* smooth operator ********************/ 02128 02129 static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) 02130 { 02131 Object *obedit= CTX_data_edit_object(C); 02132 ListBase *editnurb= object_editcurve_get(obedit); 02133 Nurb *nu; 02134 BezTriple *bezt, *beztOrig; 02135 BPoint *bp, *bpOrig; 02136 float val, newval, offset; 02137 int a, i, change = 0; 02138 02139 for(nu= editnurb->first; nu; nu= nu->next) { 02140 if(nu->bezt) { 02141 change = 0; 02142 beztOrig = MEM_dupallocN( nu->bezt ); 02143 for(bezt=nu->bezt+1, a=1; a<nu->pntsu-1; a++, bezt++) { 02144 if(bezt->f2 & SELECT) { 02145 for(i=0; i<3; i++) { 02146 val = bezt->vec[1][i]; 02147 newval = ((beztOrig+(a-1))->vec[1][i] * 0.5f) + ((beztOrig+(a+1))->vec[1][i] * 0.5f); 02148 offset = (val*((1.0f/6.0f)*5.0f)) + (newval*(1.0f/6.0f)) - val; 02149 /* offset handles */ 02150 bezt->vec[1][i] += offset; 02151 bezt->vec[0][i] += offset; 02152 bezt->vec[2][i] += offset; 02153 } 02154 change = 1; 02155 } 02156 } 02157 MEM_freeN(beztOrig); 02158 if (change) 02159 calchandlesNurb(nu); 02160 } else if (nu->bp) { 02161 bpOrig = MEM_dupallocN( nu->bp ); 02162 /* Same as above, keep these the same! */ 02163 for(bp=nu->bp+1, a=1; a<nu->pntsu-1; a++, bp++) { 02164 if(bp->f1 & SELECT) { 02165 for(i=0; i<3; i++) { 02166 val = bp->vec[i]; 02167 newval = ((bpOrig+(a-1))->vec[i] * 0.5f) + ((bpOrig+(a+1))->vec[i] * 0.5f); 02168 offset = (val*((1.0f/6.0f)*5.0f)) + (newval*(1.0f/6.0f)) - val; 02169 02170 bp->vec[i] += offset; 02171 } 02172 } 02173 } 02174 MEM_freeN(bpOrig); 02175 } 02176 } 02177 02178 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02179 DAG_id_tag_update(obedit->data, 0); 02180 02181 return OPERATOR_FINISHED; 02182 } 02183 02184 void CURVE_OT_smooth(wmOperatorType *ot) 02185 { 02186 /* identifiers */ 02187 ot->name= "Smooth"; 02188 ot->description= "Flatten angles of selected points"; 02189 ot->idname= "CURVE_OT_smooth"; 02190 02191 /* api callbacks */ 02192 ot->exec= smooth_exec; 02193 ot->poll= ED_operator_editsurfcurve; 02194 02195 /* flags */ 02196 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02197 } 02198 02199 /**************** smooth curve radius operator *************/ 02200 02201 /* TODO, make smoothing distance based */ 02202 static int smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) 02203 { 02204 Object *obedit= CTX_data_edit_object(C); 02205 ListBase *editnurb= object_editcurve_get(obedit); 02206 Nurb *nu; 02207 BezTriple *bezt; 02208 BPoint *bp; 02209 int a; 02210 02211 /* use for smoothing */ 02212 int last_sel; 02213 int start_sel, end_sel; /* selection indices, inclusive */ 02214 float start_rad, end_rad, fac, range; 02215 02216 for(nu= editnurb->first; nu; nu= nu->next) { 02217 if(nu->bezt) { 02218 02219 for (last_sel=0; last_sel < nu->pntsu; last_sel++) { 02220 /* loop over selection segments of a curve, smooth each */ 02221 02222 /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ 02223 start_sel = -1; 02224 for(bezt=nu->bezt+last_sel, a=last_sel; a<nu->pntsu; a++, bezt++) { 02225 if(bezt->f2 & SELECT) { 02226 start_sel = a; 02227 break; 02228 } 02229 } 02230 /* incase there are no other selected verts */ 02231 end_sel = start_sel; 02232 for(bezt=nu->bezt+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bezt++) { 02233 if((bezt->f2 & SELECT)==0) { 02234 break; 02235 } 02236 end_sel = a; 02237 } 02238 02239 if (start_sel == -1) { 02240 last_sel = nu->pntsu; /* next... */ 02241 } else { 02242 last_sel = end_sel; /* before we modify it */ 02243 02244 /* now blend between start and end sel */ 02245 start_rad = end_rad = -1.0; 02246 02247 if (start_sel == end_sel) { 02248 /* simple, only 1 point selected */ 02249 if (start_sel>0) start_rad = (nu->bezt+start_sel-1)->radius; 02250 if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bezt+start_sel+1)->radius; 02251 02252 if (start_rad >= 0.0f && end_rad >= 0.0f) (nu->bezt+start_sel)->radius = (start_rad + end_rad)/2; 02253 else if (start_rad >= 0.0f) (nu->bezt+start_sel)->radius = start_rad; 02254 else if (end_rad >= 0.0f) (nu->bezt+start_sel)->radius = end_rad; 02255 } else { 02256 /* if endpoints selected, then use them */ 02257 if (start_sel==0) { 02258 start_rad = (nu->bezt+start_sel)->radius; 02259 start_sel++; /* we dont want to edit the selected endpoint */ 02260 } else { 02261 start_rad = (nu->bezt+start_sel-1)->radius; 02262 } 02263 if (end_sel==nu->pntsu-1) { 02264 end_rad = (nu->bezt+end_sel)->radius; 02265 end_sel--; /* we dont want to edit the selected endpoint */ 02266 } else { 02267 end_rad = (nu->bezt+end_sel+1)->radius; 02268 } 02269 02270 /* Now Blend between the points */ 02271 range = (float)(end_sel - start_sel) + 2.0f; 02272 for(bezt=nu->bezt+start_sel, a=start_sel; a<=end_sel; a++, bezt++) { 02273 fac = (float)(1+a-start_sel) / range; 02274 bezt->radius = start_rad*(1.0f-fac) + end_rad*fac; 02275 } 02276 } 02277 } 02278 } 02279 } else if (nu->bp) { 02280 /* Same as above, keep these the same! */ 02281 for (last_sel=0; last_sel < nu->pntsu; last_sel++) { 02282 /* loop over selection segments of a curve, smooth each */ 02283 02284 /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ 02285 start_sel = -1; 02286 for(bp=nu->bp+last_sel, a=last_sel; a<nu->pntsu; a++, bp++) { 02287 if(bp->f1 & SELECT) { 02288 start_sel = a; 02289 break; 02290 } 02291 } 02292 /* incase there are no other selected verts */ 02293 end_sel = start_sel; 02294 for(bp=nu->bp+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bp++) { 02295 if((bp->f1 & SELECT)==0) { 02296 break; 02297 } 02298 end_sel = a; 02299 } 02300 02301 if (start_sel == -1) { 02302 last_sel = nu->pntsu; /* next... */ 02303 } else { 02304 last_sel = end_sel; /* before we modify it */ 02305 02306 /* now blend between start and end sel */ 02307 start_rad = end_rad = -1.0; 02308 02309 if (start_sel == end_sel) { 02310 /* simple, only 1 point selected */ 02311 if (start_sel>0) start_rad = (nu->bp+start_sel-1)->radius; 02312 if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bp+start_sel+1)->radius; 02313 02314 if (start_rad >= 0.0f && end_rad >= 0.0f) (nu->bp+start_sel)->radius = (start_rad + end_rad)/2; 02315 else if (start_rad >= 0.0f) (nu->bp+start_sel)->radius = start_rad; 02316 else if (end_rad >= 0.0f) (nu->bp+start_sel)->radius = end_rad; 02317 } else { 02318 /* if endpoints selected, then use them */ 02319 if (start_sel==0) { 02320 start_rad = (nu->bp+start_sel)->radius; 02321 start_sel++; /* we dont want to edit the selected endpoint */ 02322 } else { 02323 start_rad = (nu->bp+start_sel-1)->radius; 02324 } 02325 if (end_sel==nu->pntsu-1) { 02326 end_rad = (nu->bp+end_sel)->radius; 02327 end_sel--; /* we dont want to edit the selected endpoint */ 02328 } else { 02329 end_rad = (nu->bp+end_sel+1)->radius; 02330 } 02331 02332 /* Now Blend between the points */ 02333 range = (float)(end_sel - start_sel) + 2.0f; 02334 for(bp=nu->bp+start_sel, a=start_sel; a<=end_sel; a++, bp++) { 02335 fac = (float)(1+a-start_sel) / range; 02336 bp->radius = start_rad*(1.0f-fac) + end_rad*fac; 02337 } 02338 } 02339 } 02340 } 02341 } 02342 } 02343 02344 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02345 DAG_id_tag_update(obedit->data, 0); 02346 02347 return OPERATOR_FINISHED; 02348 } 02349 02350 void CURVE_OT_smooth_radius(wmOperatorType *ot) 02351 { 02352 /* identifiers */ 02353 ot->name= "Smooth Curve Radius"; 02354 ot->description= "Flatten radiuses of selected points"; 02355 ot->idname= "CURVE_OT_smooth_radius"; 02356 02357 /* api clastbacks */ 02358 ot->exec= smooth_radius_exec; 02359 ot->poll= ED_operator_editsurfcurve; 02360 02361 /* flags */ 02362 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02363 } 02364 02365 /***************** selection utility *************************/ 02366 02367 /* next == 1 -> select next */ 02368 /* next == -1 -> select previous */ 02369 /* cont == 1 -> select continuously */ 02370 /* selstatus, inverts behaviour */ 02371 static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus) 02372 { 02373 Nurb *nu; 02374 BezTriple *bezt; 02375 BPoint *bp; 02376 int a; 02377 short lastsel= 0; 02378 02379 if(next==0) return; 02380 02381 for(nu= editnurb->first; nu; nu= nu->next) { 02382 lastsel=0; 02383 if(nu->type == CU_BEZIER) { 02384 a= nu->pntsu; 02385 bezt= nu->bezt; 02386 if(next < 0) bezt= (nu->bezt + (a-1)); 02387 while(a--) { 02388 if(a-abs(next) < 0) break; 02389 if((lastsel==0) && (bezt->hide==0) && ((bezt->f2 & SELECT) || (selstatus==0))) { 02390 bezt+=next; 02391 if(!(bezt->f2 & SELECT) || (selstatus==0)) { 02392 short sel= select_beztriple(bezt, selstatus, 1, VISIBLE); 02393 if((sel==1) && (cont==0)) lastsel= 1; 02394 } 02395 } 02396 else { 02397 bezt+=next; 02398 lastsel= 0; 02399 } 02400 /* move around in zigzag way so that we go through each */ 02401 bezt-=(next-next/abs(next)); 02402 } 02403 } 02404 else { 02405 a= nu->pntsu*nu->pntsv; 02406 bp= nu->bp; 02407 if(next < 0) bp= (nu->bp + (a-1)); 02408 while(a--) { 02409 if(a-abs(next) < 0) break; 02410 if((lastsel==0) && (bp->hide==0) && ((bp->f1 & SELECT) || (selstatus==0))) { 02411 bp+=next; 02412 if(!(bp->f1 & SELECT) || (selstatus==0)) { 02413 short sel= select_bpoint(bp, selstatus, 1, VISIBLE); 02414 if((sel==1) && (cont==0)) lastsel= 1; 02415 } 02416 } 02417 else { 02418 bp+=next; 02419 lastsel= 0; 02420 } 02421 /* move around in zigzag way so that we go through each */ 02422 bp-=(next-next/abs(next)); 02423 } 02424 } 02425 } 02426 } 02427 02428 /**************** select start/end operators **************/ 02429 02430 /* (de)selects first or last of visible part of each Nurb depending on selFirst */ 02431 /* selFirst: defines the end of which to select */ 02432 /* doswap: defines if selection state of each first/last control point is swapped */ 02433 /* selstatus: selection status in case doswap is false */ 02434 void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus) 02435 { 02436 ListBase *editnurb= object_editcurve_get(obedit); 02437 Nurb *nu; 02438 BPoint *bp; 02439 BezTriple *bezt; 02440 Curve *cu; 02441 int a; 02442 02443 if(obedit==NULL) return; 02444 02445 cu= (Curve*)obedit->data; 02446 cu->lastsel= NULL; 02447 02448 for(nu= editnurb->first; nu; nu= nu->next) { 02449 if(nu->type == CU_BEZIER) { 02450 a= nu->pntsu; 02451 02452 /* which point? */ 02453 if(selfirst==0) { /* select last */ 02454 bezt= (nu->bezt + (a-1)); 02455 } 02456 else { /* select first */ 02457 bezt= nu->bezt; 02458 } 02459 02460 while(a--) { 02461 short sel; 02462 if(doswap) sel= swap_selection_beztriple(bezt); 02463 else sel= select_beztriple(bezt, selstatus, 1, VISIBLE); 02464 02465 if(sel==1) break; 02466 } 02467 } 02468 else { 02469 a= nu->pntsu*nu->pntsv; 02470 02471 /* which point? */ 02472 if(selfirst==0) { /* select last */ 02473 bp= (nu->bp + (a-1)); 02474 } 02475 else{ /* select first */ 02476 bp= nu->bp; 02477 } 02478 02479 while(a--) { 02480 if (bp->hide == 0) { 02481 short sel; 02482 if(doswap) sel= swap_selection_bpoint(bp); 02483 else sel= select_bpoint(bp, selstatus, 1, VISIBLE); 02484 02485 if(sel==1) break; 02486 } 02487 } 02488 } 02489 } 02490 } 02491 02492 static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) 02493 { 02494 Object *obedit= CTX_data_edit_object(C); 02495 02496 selectend_nurb(obedit, FIRST, 1, DESELECT); 02497 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02498 02499 return OPERATOR_FINISHED; 02500 } 02501 02502 void CURVE_OT_de_select_first(wmOperatorType *ot) 02503 { 02504 /* identifiers */ 02505 ot->name= "Select or Deselect First"; 02506 ot->idname= "CURVE_OT_de_select_first"; 02507 02508 /* api cfirstbacks */ 02509 ot->exec= de_select_first_exec; 02510 ot->poll= ED_operator_editcurve; 02511 02512 /* flags */ 02513 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02514 } 02515 02516 static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) 02517 { 02518 Object *obedit= CTX_data_edit_object(C); 02519 02520 selectend_nurb(obedit, LAST, 1, DESELECT); 02521 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02522 02523 return OPERATOR_FINISHED; 02524 } 02525 02526 void CURVE_OT_de_select_last(wmOperatorType *ot) 02527 { 02528 /* identifiers */ 02529 ot->name= "Select or Deselect Last"; 02530 ot->idname= "CURVE_OT_de_select_last"; 02531 02532 /* api clastbacks */ 02533 ot->exec= de_select_last_exec; 02534 ot->poll= ED_operator_editcurve; 02535 02536 /* flags */ 02537 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02538 } 02539 02540 /******************* de select all operator ***************/ 02541 02542 static short nurb_has_selected_cps(ListBase *editnurb) 02543 { 02544 Nurb *nu; 02545 BezTriple *bezt; 02546 BPoint *bp; 02547 int a; 02548 02549 for(nu= editnurb->first; nu; nu= nu->next) { 02550 if(nu->type == CU_BEZIER) { 02551 a= nu->pntsu; 02552 bezt= nu->bezt; 02553 while(a--) { 02554 if(bezt->hide==0) { 02555 if((bezt->f1 & SELECT) 02556 || (bezt->f2 & SELECT) 02557 || (bezt->f3 & SELECT)) return 1; 02558 } 02559 bezt++; 02560 } 02561 } 02562 else { 02563 a= nu->pntsu*nu->pntsv; 02564 bp= nu->bp; 02565 while(a--) { 02566 if((bp->hide==0) && (bp->f1 & SELECT)) return 1; 02567 bp++; 02568 } 02569 } 02570 } 02571 02572 return 0; 02573 } 02574 02575 static int de_select_all_exec(bContext *C, wmOperator *op) 02576 { 02577 Object *obedit= CTX_data_edit_object(C); 02578 ListBase *editnurb= object_editcurve_get(obedit); 02579 int action = RNA_enum_get(op->ptr, "action"); 02580 02581 if (action == SEL_TOGGLE) { 02582 action = SEL_SELECT; 02583 if(nurb_has_selected_cps(editnurb)) 02584 action = SEL_DESELECT; 02585 } 02586 02587 switch (action) { 02588 case SEL_SELECT: 02589 CU_select_all(obedit); 02590 break; 02591 case SEL_DESELECT: 02592 CU_deselect_all(obedit); 02593 break; 02594 case SEL_INVERT: 02595 CU_select_swap(obedit); 02596 break; 02597 } 02598 02599 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02600 02601 return OPERATOR_FINISHED; 02602 } 02603 02604 void CURVE_OT_select_all(wmOperatorType *ot) 02605 { 02606 /* identifiers */ 02607 ot->name= "Select or Deselect All"; 02608 ot->idname= "CURVE_OT_select_all"; 02609 02610 /* api callbacks */ 02611 ot->exec= de_select_all_exec; 02612 ot->poll= ED_operator_editsurfcurve; 02613 02614 /* flags */ 02615 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02616 02617 /* properties */ 02618 WM_operator_properties_select_all(ot); 02619 } 02620 02621 /********************** hide operator *********************/ 02622 02623 static int hide_exec(bContext *C, wmOperator *op) 02624 { 02625 Object *obedit= CTX_data_edit_object(C); 02626 Curve *cu= obedit->data; 02627 ListBase *editnurb= object_editcurve_get(obedit); 02628 Nurb *nu; 02629 BPoint *bp; 02630 BezTriple *bezt; 02631 int a, sel, invert= RNA_boolean_get(op->ptr, "unselected"); 02632 02633 for(nu= editnurb->first; nu; nu= nu->next) { 02634 if(nu->type == CU_BEZIER) { 02635 bezt= nu->bezt; 02636 a= nu->pntsu; 02637 sel= 0; 02638 while(a--) { 02639 if(invert == 0 && BEZSELECTED_HIDDENHANDLES(cu, bezt)) { 02640 select_beztriple(bezt, DESELECT, 1, HIDDEN); 02641 bezt->hide= 1; 02642 } 02643 else if(invert && !BEZSELECTED_HIDDENHANDLES(cu, bezt)) { 02644 select_beztriple(bezt, DESELECT, 1, HIDDEN); 02645 bezt->hide= 1; 02646 } 02647 if(bezt->hide) sel++; 02648 bezt++; 02649 } 02650 if(sel==nu->pntsu) nu->hide= 1; 02651 } 02652 else { 02653 bp= nu->bp; 02654 a= nu->pntsu*nu->pntsv; 02655 sel= 0; 02656 while(a--) { 02657 if(invert==0 && (bp->f1 & SELECT)) { 02658 select_bpoint(bp, DESELECT, 1, HIDDEN); 02659 bp->hide= 1; 02660 } 02661 else if(invert && (bp->f1 & SELECT)==0) { 02662 select_bpoint(bp, DESELECT, 1, HIDDEN); 02663 bp->hide= 1; 02664 } 02665 if(bp->hide) sel++; 02666 bp++; 02667 } 02668 if(sel==nu->pntsu*nu->pntsv) nu->hide= 1; 02669 } 02670 } 02671 02672 DAG_id_tag_update(obedit->data, 0); 02673 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02674 02675 return OPERATOR_FINISHED; 02676 } 02677 02678 void CURVE_OT_hide(wmOperatorType *ot) 02679 { 02680 /* identifiers */ 02681 ot->name= "Hide Selected"; 02682 ot->idname= "CURVE_OT_hide"; 02683 02684 /* api callbacks */ 02685 ot->exec= hide_exec; 02686 ot->poll= ED_operator_editsurfcurve; 02687 02688 /* flags */ 02689 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02690 02691 /* props */ 02692 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); 02693 } 02694 02695 /********************** reveal operator *********************/ 02696 02697 static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) 02698 { 02699 Object *obedit= CTX_data_edit_object(C); 02700 ListBase *editnurb= object_editcurve_get(obedit); 02701 Nurb *nu; 02702 BPoint *bp; 02703 BezTriple *bezt; 02704 int a; 02705 02706 for(nu= editnurb->first; nu; nu= nu->next) { 02707 nu->hide= 0; 02708 if(nu->type == CU_BEZIER) { 02709 bezt= nu->bezt; 02710 a= nu->pntsu; 02711 while(a--) { 02712 if(bezt->hide) { 02713 select_beztriple(bezt, SELECT, 1, HIDDEN); 02714 bezt->hide= 0; 02715 } 02716 bezt++; 02717 } 02718 } 02719 else { 02720 bp= nu->bp; 02721 a= nu->pntsu*nu->pntsv; 02722 while(a--) { 02723 if(bp->hide) { 02724 select_bpoint(bp, SELECT, 1, HIDDEN); 02725 bp->hide= 0; 02726 } 02727 bp++; 02728 } 02729 } 02730 } 02731 02732 DAG_id_tag_update(obedit->data, 0); 02733 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02734 02735 return OPERATOR_FINISHED; 02736 } 02737 02738 void CURVE_OT_reveal(wmOperatorType *ot) 02739 { 02740 /* identifiers */ 02741 ot->name= "Reveal Hidden"; 02742 ot->idname= "CURVE_OT_reveal"; 02743 02744 /* api callbacks */ 02745 ot->exec= reveal_exec; 02746 ot->poll= ED_operator_editsurfcurve; 02747 02748 /* flags */ 02749 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02750 } 02751 02752 /********************** subdivide operator *********************/ 02753 02758 static void subdividenurb(Object *obedit, int number_cuts) 02759 { 02760 Curve *cu= obedit->data; 02761 EditNurb *editnurb= cu->editnurb; 02762 Nurb *nu; 02763 BezTriple *prevbezt, *bezt, *beztnew, *beztn; 02764 BPoint *bp, *prevbp, *bpnew, *bpn; 02765 float vec[15]; 02766 int a, b, sel, amount, *usel, *vsel, i; 02767 float factor; 02768 02769 // printf("*** subdivideNurb: entering subdivide\n"); 02770 02771 for(nu= editnurb->nurbs.first; nu; nu= nu->next) { 02772 amount= 0; 02773 if(nu->type == CU_BEZIER) { 02774 /* 02775 Insert a point into a 2D Bezier curve. 02776 Endpoints are preserved. Otherwise, all selected and inserted points are 02777 newly created. Old points are discarded. 02778 */ 02779 /* count */ 02780 if(nu->flagu & CU_NURB_CYCLIC) { 02781 a= nu->pntsu; 02782 bezt= nu->bezt; 02783 prevbezt= bezt+(a-1); 02784 } 02785 else { 02786 a= nu->pntsu-1; 02787 prevbezt= nu->bezt; 02788 bezt= prevbezt+1; 02789 } 02790 while(a--) { 02791 if( BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) amount+=number_cuts; 02792 prevbezt= bezt; 02793 bezt++; 02794 } 02795 02796 if(amount) { 02797 /* insert */ 02798 beztnew = 02799 (BezTriple*)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb"); 02800 beztn= beztnew; 02801 if(nu->flagu & CU_NURB_CYCLIC) { 02802 a= nu->pntsu; 02803 bezt= nu->bezt; 02804 prevbezt= bezt+(a-1); 02805 } 02806 else { 02807 a= nu->pntsu-1; 02808 prevbezt= nu->bezt; 02809 bezt= prevbezt+1; 02810 } 02811 while(a--) { 02812 memcpy(beztn, prevbezt, sizeof(BezTriple)); 02813 keyIndex_updateBezt(editnurb, prevbezt, beztn, 1); 02814 beztn++; 02815 02816 if( BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { 02817 float prevvec[3][3]; 02818 02819 memcpy(prevvec, prevbezt->vec, sizeof(float) * 9); 02820 02821 for (i = 0; i < number_cuts; i++) { 02822 factor = 1.0f / (number_cuts + 1 - i); 02823 02824 memcpy(beztn, bezt, sizeof(BezTriple)); 02825 02826 /* midpoint subdividing */ 02827 interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor); 02828 interp_v3_v3v3(vec+3, prevvec[2], bezt->vec[0], factor); 02829 interp_v3_v3v3(vec+6, bezt->vec[0], bezt->vec[1], factor); 02830 02831 interp_v3_v3v3(vec+9, vec, vec+3, factor); 02832 interp_v3_v3v3(vec+12, vec+3, vec+6, factor); 02833 02834 /* change handle of prev beztn */ 02835 copy_v3_v3((beztn-1)->vec[2], vec); 02836 /* new point */ 02837 copy_v3_v3(beztn->vec[0], vec+9); 02838 interp_v3_v3v3(beztn->vec[1], vec+9, vec+12, factor); 02839 copy_v3_v3(beztn->vec[2], vec+12); 02840 /* handle of next bezt */ 02841 if(a==0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) {copy_v3_v3(beztnew->vec[0], vec+6);} 02842 else {copy_v3_v3(bezt->vec[0], vec+6);} 02843 02844 beztn->radius = (prevbezt->radius + bezt->radius)/2; 02845 beztn->weight = (prevbezt->weight + bezt->weight)/2; 02846 02847 memcpy(prevvec, beztn->vec, sizeof(float) * 9); 02848 beztn++; 02849 } 02850 } 02851 02852 prevbezt= bezt; 02853 bezt++; 02854 } 02855 /* last point */ 02856 if((nu->flagu & CU_NURB_CYCLIC)==0) { 02857 memcpy(beztn, prevbezt, sizeof(BezTriple)); 02858 keyIndex_updateBezt(editnurb, prevbezt, beztn, 1); 02859 } 02860 02861 MEM_freeN(nu->bezt); 02862 nu->bezt= beztnew; 02863 nu->pntsu+= amount; 02864 02865 calchandlesNurb(nu); 02866 } 02867 } /* End of 'if(nu->type == CU_BEZIER)' */ 02868 else if (nu->pntsv==1) { 02869 /* 02870 All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves 02871 are handled together with the regular NURB plane division, as it 02872 should be. I split it off just now, let's see if it is 02873 stable... nzc 30-5-'00 02874 */ 02875 /* count */ 02876 if(nu->flagu & CU_NURB_CYCLIC) { 02877 a= nu->pntsu; 02878 bp= nu->bp; 02879 prevbp= bp+(a-1); 02880 } 02881 else { 02882 a= nu->pntsu-1; 02883 prevbp= nu->bp; 02884 bp= prevbp+1; 02885 } 02886 while(a--) { 02887 if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount+=number_cuts; 02888 prevbp= bp; 02889 bp++; 02890 } 02891 02892 if(amount) { 02893 /* insert */ 02894 bpnew = 02895 (BPoint*)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2"); 02896 bpn= bpnew; 02897 02898 if(nu->flagu & CU_NURB_CYCLIC) { 02899 a= nu->pntsu; 02900 bp= nu->bp; 02901 prevbp= bp+(a-1); 02902 } 02903 else { 02904 a= nu->pntsu-1; 02905 prevbp= nu->bp; 02906 bp= prevbp+1; 02907 } 02908 while(a--) { 02909 memcpy(bpn, prevbp, sizeof(BPoint)); 02910 keyIndex_updateBP(editnurb, prevbp, bpn, 1); 02911 bpn++; 02912 02913 if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) { 02914 // printf("*** subdivideNurb: insert 'linear' point\n"); 02915 for (i = 0; i < number_cuts; i++) { 02916 factor = (float)(i + 1) / (number_cuts + 1); 02917 02918 memcpy(bpn, bp, sizeof(BPoint)); 02919 interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); 02920 bpn++; 02921 } 02922 02923 } 02924 prevbp= bp; 02925 bp++; 02926 } 02927 if((nu->flagu & CU_NURB_CYCLIC)==0) { /* last point */ 02928 memcpy(bpn, prevbp, sizeof(BPoint)); 02929 keyIndex_updateBP(editnurb, prevbp, bpn, 1); 02930 } 02931 02932 MEM_freeN(nu->bp); 02933 nu->bp= bpnew; 02934 nu->pntsu+= amount; 02935 02936 if(nu->type & CU_NURBS) { 02937 nurbs_knot_calc_u(nu); 02938 } 02939 } 02940 } /* End of 'else if(nu->pntsv==1)' */ 02941 else if(nu->type == CU_NURBS) { 02942 /* This is a very strange test ... */ 02984 /* selection-arrays */ 02985 usel= MEM_callocN(sizeof(int)*nu->pntsu, "subivideNurb3"); 02986 vsel= MEM_callocN(sizeof(int)*nu->pntsv, "subivideNurb3"); 02987 sel= 0; 02988 02989 /* Count the number of selected points. */ 02990 bp= nu->bp; 02991 for(a=0; a<nu->pntsv; a++) { 02992 for(b=0; b<nu->pntsu; b++) { 02993 if(bp->f1 & SELECT) { 02994 usel[b]++; 02995 vsel[a]++; 02996 sel++; 02997 } 02998 bp++; 02999 } 03000 } 03001 if( sel == (nu->pntsu*nu->pntsv) ) { /* subdivide entire nurb */ 03002 /* Global subdivision is a special case of partial 03003 subdivision. Strange it is considered separately... */ 03004 03005 /* count of nodes (after subdivision) along U axis */ 03006 int countu= nu->pntsu + (nu->pntsu - 1) * number_cuts; 03007 03008 /* total count of nodes after subdivision */ 03009 int tot= ((number_cuts+1)*nu->pntsu-number_cuts)*((number_cuts+1)*nu->pntsv-number_cuts); 03010 03011 bpn=bpnew= MEM_mallocN( tot*sizeof(BPoint), "subdivideNurb4"); 03012 bp= nu->bp; 03013 /* first subdivide rows */ 03014 for(a=0; a<nu->pntsv; a++) { 03015 for(b=0; b<nu->pntsu; b++) { 03016 *bpn= *bp; 03017 keyIndex_updateBP(editnurb, bp, bpn, 1); 03018 bpn++; 03019 bp++; 03020 if(b<nu->pntsu-1) { 03021 prevbp= bp-1; 03022 for (i = 0; i < number_cuts; i++) { 03023 factor = (float)(i + 1) / (number_cuts + 1); 03024 *bpn= *bp; 03025 interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); 03026 bpn++; 03027 } 03028 } 03029 } 03030 bpn+= number_cuts * countu; 03031 } 03032 /* now insert new */ 03033 bpn= bpnew+((number_cuts+1)*nu->pntsu - number_cuts); 03034 bp= bpnew+(number_cuts+1)*((number_cuts+1)*nu->pntsu-number_cuts); 03035 prevbp= bpnew; 03036 for(a=1; a<nu->pntsv; a++) { 03037 03038 for(b=0; b<(number_cuts+1)*nu->pntsu-number_cuts; b++) { 03039 BPoint *tmp= bpn; 03040 for (i = 0; i < number_cuts; i++) { 03041 factor = (float)(i + 1) / (number_cuts + 1); 03042 *tmp= *bp; 03043 interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor); 03044 tmp += countu; 03045 } 03046 bp++; 03047 prevbp++; 03048 bpn++; 03049 } 03050 bp+= number_cuts * countu; 03051 bpn+= number_cuts * countu; 03052 prevbp+= number_cuts * countu; 03053 } 03054 MEM_freeN(nu->bp); 03055 nu->bp= bpnew; 03056 nu->pntsu= (number_cuts+1)*nu->pntsu-number_cuts; 03057 nu->pntsv= (number_cuts+1)*nu->pntsv-number_cuts; 03058 nurbs_knot_calc_u(nu); 03059 nurbs_knot_calc_v(nu); 03060 } /* End of 'if(sel== nu->pntsu*nu->pntsv)' (subdivide entire NURB) */ 03061 else { 03062 /* subdivide in v direction? */ 03063 sel= 0; 03064 for(a=0; a<nu->pntsv-1; a++) { 03065 if(vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu) sel+=number_cuts; 03066 } 03067 03068 if(sel) { /* V ! */ 03069 bpn=bpnew= MEM_mallocN( (sel+nu->pntsv)*nu->pntsu*sizeof(BPoint), "subdivideNurb4"); 03070 bp= nu->bp; 03071 for(a=0; a<nu->pntsv; a++) { 03072 for(b=0; b<nu->pntsu; b++) { 03073 *bpn= *bp; 03074 keyIndex_updateBP(editnurb, bp, bpn, 1); 03075 bpn++; 03076 bp++; 03077 } 03078 if( (a<nu->pntsv-1) && vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu ) { 03079 for (i = 0; i < number_cuts; i++) { 03080 factor = (float)(i + 1) / (number_cuts + 1); 03081 prevbp= bp- nu->pntsu; 03082 for(b=0; b<nu->pntsu; b++) { 03083 /* 03084 This simple bisection must be replaces by a 03085 subtle resampling of a number of points. Our 03086 task is made slightly easier because each 03087 point in our curve is a separate data 03088 node. (is it?) 03089 */ 03090 *bpn= *prevbp; 03091 interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); 03092 bpn++; 03093 03094 prevbp++; 03095 bp++; 03096 } 03097 bp-= nu->pntsu; 03098 } 03099 } 03100 } 03101 MEM_freeN(nu->bp); 03102 nu->bp= bpnew; 03103 nu->pntsv+= sel; 03104 nurbs_knot_calc_v(nu); 03105 } 03106 else { 03107 /* or in u direction? */ 03108 sel= 0; 03109 for(a=0; a<nu->pntsu-1; a++) { 03110 if(usel[a]==nu->pntsv && usel[a+1]==nu->pntsv) sel+=number_cuts; 03111 } 03112 03113 if(sel) { /* U ! */ 03114 /* Inserting U points is sort of 'default' Flat curves only get */ 03115 /* U points inserted in them. */ 03116 bpn=bpnew= MEM_mallocN( (sel+nu->pntsu)*nu->pntsv*sizeof(BPoint), "subdivideNurb4"); 03117 bp= nu->bp; 03118 for(a=0; a<nu->pntsv; a++) { 03119 for(b=0; b<nu->pntsu; b++) { 03120 *bpn= *bp; 03121 keyIndex_updateBP(editnurb, bp, bpn, 1); 03122 bpn++; 03123 bp++; 03124 if( (b<nu->pntsu-1) && usel[b]==nu->pntsv && usel[b+1]==nu->pntsv ) { 03125 /* 03126 One thing that bugs me here is that the 03127 orders of things are not the same as in 03128 the JW piece. Also, this implies that we 03129 handle at most 3rd order curves? I miss 03130 some symmetry here... 03131 */ 03132 for (i = 0; i < number_cuts; i++) { 03133 factor = (float)(i + 1) / (number_cuts + 1); 03134 prevbp= bp- 1; 03135 *bpn= *prevbp; 03136 interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); 03137 bpn++; 03138 } 03139 } 03140 } 03141 } 03142 MEM_freeN(nu->bp); 03143 nu->bp= bpnew; 03144 nu->pntsu+= sel; 03145 nurbs_knot_calc_u(nu); /* shift knots forward */ 03146 } 03147 } 03148 } 03149 MEM_freeN(usel); 03150 MEM_freeN(vsel); 03151 03152 } /* End of 'if(nu->type == CU_NURBS)' */ 03153 } 03154 } 03155 03156 static int subdivide_exec(bContext *C, wmOperator *op) 03157 { 03158 Object *obedit= CTX_data_edit_object(C); 03159 int number_cuts= RNA_int_get(op->ptr, "number_cuts"); 03160 03161 subdividenurb(obedit, number_cuts); 03162 03163 if(ED_curve_updateAnimPaths(obedit)) 03164 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 03165 03166 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 03167 DAG_id_tag_update(obedit->data, 0); 03168 03169 return OPERATOR_FINISHED; 03170 } 03171 03172 void CURVE_OT_subdivide(wmOperatorType *ot) 03173 { 03174 /* identifiers */ 03175 ot->name= "Subdivide"; 03176 ot->description= "Subdivide selected segments"; 03177 ot->idname= "CURVE_OT_subdivide"; 03178 03179 /* api callbacks */ 03180 ot->exec= subdivide_exec; 03181 ot->poll= ED_operator_editsurfcurve; 03182 03183 /* flags */ 03184 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03185 03186 RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of cuts", "", 1, 10); 03187 } 03188 03189 /******************** find nearest ************************/ 03190 03191 static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y) 03192 { 03193 struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } *data = userData; 03194 03195 short flag; 03196 short temp; 03197 03198 if (bp) { 03199 flag = bp->f1; 03200 } else { 03201 if (beztindex==0) { 03202 flag = bezt->f1; 03203 } else if (beztindex==1) { 03204 flag = bezt->f2; 03205 } else { 03206 flag = bezt->f3; 03207 } 03208 } 03209 03210 temp = abs(data->mval[0]-x) + abs(data->mval[1]-y); 03211 if ((flag&1)==data->select) temp += 5; 03212 if (bezt && beztindex==1) temp += 3; /* middle points get a small disadvantage */ 03213 03214 if (temp<data->dist) { 03215 data->dist = temp; 03216 03217 data->bp = bp; 03218 data->bezt = bezt; 03219 data->nurb = nu; 03220 data->hpoint = bezt?beztindex:0; 03221 } 03222 } 03223 03224 static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], Nurb **nurb, BezTriple **bezt, BPoint **bp) 03225 { 03226 /* sel==1: selected gets a disadvantage */ 03227 /* in nurb and bezt or bp the nearest is written */ 03228 /* return 0 1 2: handlepunt */ 03229 struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } data = {NULL}; 03230 03231 data.dist = 100; 03232 data.hpoint = 0; 03233 data.select = sel; 03234 data.mval[0] = mval[0]; 03235 data.mval[1] = mval[1]; 03236 03237 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); 03238 nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data); 03239 03240 *nurb = data.nurb; 03241 *bezt = data.bezt; 03242 *bp = data.bp; 03243 03244 return data.hpoint; 03245 } 03246 03247 static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt, BPoint **bp) 03248 { 03249 /* in nu and (bezt or bp) selected are written if there's 1 sel. */ 03250 /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ 03251 Nurb *nu1; 03252 BezTriple *bezt1; 03253 BPoint *bp1; 03254 int a; 03255 03256 *nu= NULL; 03257 *bezt= NULL; 03258 *bp= NULL; 03259 for(nu1= editnurb->first; nu1; nu1= nu1->next) { 03260 if(nu1->type == CU_BEZIER) { 03261 bezt1= nu1->bezt; 03262 a= nu1->pntsu; 03263 while(a--) { 03264 if( (bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT) ) { 03265 if(*nu != NULL && *nu != nu1) { 03266 *nu= NULL; 03267 *bp= NULL; 03268 *bezt= NULL; 03269 return; 03270 } 03271 else if(*bezt || *bp) { 03272 *bp= NULL; 03273 *bezt= NULL; 03274 } 03275 else { 03276 *bezt= bezt1; 03277 *nu= nu1; 03278 } 03279 } 03280 bezt1++; 03281 } 03282 } 03283 else { 03284 bp1= nu1->bp; 03285 a= nu1->pntsu*nu1->pntsv; 03286 while(a--) { 03287 if( bp1->f1 & 1 ) { 03288 if(*nu != NULL && *nu != nu1) { 03289 *bp= NULL; 03290 *bezt= NULL; 03291 *nu= NULL; 03292 return; 03293 } 03294 else if(*bezt || *bp) { 03295 *bp= NULL; 03296 *bezt= NULL; 03297 } 03298 else { 03299 *bp= bp1; 03300 *nu= nu1; 03301 } 03302 } 03303 bp1++; 03304 } 03305 } 03306 } 03307 } 03308 03309 /***************** set spline type operator *******************/ 03310 03311 static int convertspline(short type, Nurb *nu) 03312 { 03313 BezTriple *bezt; 03314 BPoint *bp; 03315 int a, c, nr; 03316 03317 if(nu->type == CU_POLY) { 03318 if(type==CU_BEZIER) { /* to Bezier with vecthandles */ 03319 nr= nu->pntsu; 03320 bezt = 03321 (BezTriple*)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2"); 03322 nu->bezt= bezt; 03323 a= nr; 03324 bp= nu->bp; 03325 while(a--) { 03326 copy_v3_v3(bezt->vec[1], bp->vec); 03327 bezt->f1=bezt->f2=bezt->f3= bp->f1; 03328 bezt->h1= bezt->h2= HD_VECT; 03329 bezt->weight= bp->weight; 03330 bezt->radius= bp->radius; 03331 bp++; 03332 bezt++; 03333 } 03334 MEM_freeN(nu->bp); 03335 nu->bp= NULL; 03336 nu->pntsu= nr; 03337 nu->type = CU_BEZIER; 03338 calchandlesNurb(nu); 03339 } 03340 else if(type==CU_NURBS) { 03341 nu->type = CU_NURBS; 03342 nu->orderu= 4; 03343 nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ 03344 nurbs_knot_calc_u(nu); 03345 a= nu->pntsu*nu->pntsv; 03346 bp= nu->bp; 03347 while(a--) { 03348 bp->vec[3]= 1.0; 03349 bp++; 03350 } 03351 } 03352 } 03353 else if(nu->type == CU_BEZIER) { /* Bezier */ 03354 if(type==CU_POLY || type==CU_NURBS) { 03355 nr= 3*nu->pntsu; 03356 nu->bp = MEM_callocN(nr * sizeof(BPoint), "setsplinetype"); 03357 a= nu->pntsu; 03358 bezt= nu->bezt; 03359 bp= nu->bp; 03360 while(a--) { 03361 if(type==CU_POLY && bezt->h1==HD_VECT && bezt->h2==HD_VECT) { 03362 /* vector handle becomes 1 poly vertice */ 03363 copy_v3_v3(bp->vec, bezt->vec[1]); 03364 bp->vec[3]= 1.0; 03365 bp->f1= bezt->f2; 03366 nr-= 2; 03367 bp->radius= bezt->radius; 03368 bp->weight= bezt->weight; 03369 bp++; 03370 } 03371 else { 03372 for(c=0;c<3;c++) { 03373 copy_v3_v3(bp->vec, bezt->vec[c]); 03374 bp->vec[3]= 1.0; 03375 if(c==0) bp->f1= bezt->f1; 03376 else if(c==1) bp->f1= bezt->f2; 03377 else bp->f1= bezt->f3; 03378 bp->radius= bezt->radius; 03379 bp->weight= bezt->weight; 03380 bp++; 03381 } 03382 } 03383 bezt++; 03384 } 03385 MEM_freeN(nu->bezt); 03386 nu->bezt= NULL; 03387 nu->pntsu= nr; 03388 nu->pntsv= 1; 03389 nu->orderu= 4; 03390 nu->orderv= 1; 03391 nu->type = type; 03392 if(nu->flagu & CU_NURB_CYCLIC) c= nu->orderu-1; 03393 else c= 0; 03394 if(type== CU_NURBS) { 03395 nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ 03396 nu->flagu |= CU_NURB_BEZIER; 03397 nurbs_knot_calc_u(nu); 03398 } 03399 } 03400 } 03401 else if(nu->type == CU_NURBS) { 03402 if(type==CU_POLY) { 03403 nu->type = CU_POLY; 03404 if(nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */ 03405 nu->knotsu= NULL; 03406 if(nu->knotsv) MEM_freeN(nu->knotsv); 03407 nu->knotsv= NULL; 03408 } 03409 else if(type==CU_BEZIER) { /* to Bezier */ 03410 nr= nu->pntsu/3; 03411 03412 if(nr<2) 03413 return 1; /* conversion impossible */ 03414 else { 03415 bezt = MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2"); 03416 nu->bezt= bezt; 03417 a= nr; 03418 bp= nu->bp; 03419 while(a--) { 03420 copy_v3_v3(bezt->vec[0], bp->vec); 03421 bezt->f1= bp->f1; 03422 bp++; 03423 copy_v3_v3(bezt->vec[1], bp->vec); 03424 bezt->f2= bp->f1; 03425 bp++; 03426 copy_v3_v3(bezt->vec[2], bp->vec); 03427 bezt->f3= bp->f1; 03428 bezt->radius= bp->radius; 03429 bezt->weight= bp->weight; 03430 bp++; 03431 bezt++; 03432 } 03433 MEM_freeN(nu->bp); 03434 nu->bp= NULL; 03435 MEM_freeN(nu->knotsu); 03436 nu->knotsu= NULL; 03437 nu->pntsu= nr; 03438 nu->type = CU_BEZIER; 03439 } 03440 } 03441 } 03442 03443 return 0; 03444 } 03445 03446 void ED_nurb_set_spline_type(Nurb *nu, int type) 03447 { 03448 convertspline(type, nu); 03449 } 03450 03451 static int set_spline_type_exec(bContext *C, wmOperator *op) 03452 { 03453 Object *obedit= CTX_data_edit_object(C); 03454 ListBase *editnurb= object_editcurve_get(obedit); 03455 Nurb *nu; 03456 int changed=0, type= RNA_enum_get(op->ptr, "type"); 03457 03458 if(type==CU_CARDINAL || type==CU_BSPLINE) { 03459 BKE_report(op->reports, RPT_ERROR, "Not implemented yet"); 03460 return OPERATOR_CANCELLED; 03461 } 03462 03463 for(nu= editnurb->first; nu; nu= nu->next) { 03464 if(isNurbsel(nu)) { 03465 if(convertspline(type, nu)) 03466 BKE_report(op->reports, RPT_ERROR, "No conversion possible"); 03467 else 03468 changed= 1; 03469 } 03470 } 03471 03472 if(changed) { 03473 if(ED_curve_updateAnimPaths(obedit)) 03474 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 03475 03476 DAG_id_tag_update(obedit->data, 0); 03477 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 03478 03479 return OPERATOR_FINISHED; 03480 } 03481 else { 03482 return OPERATOR_CANCELLED; 03483 } 03484 } 03485 03486 void CURVE_OT_spline_type_set(wmOperatorType *ot) 03487 { 03488 static EnumPropertyItem type_items[]= { 03489 {CU_POLY, "POLY", 0, "Poly", ""}, 03490 {CU_BEZIER, "BEZIER", 0, "Bezier", ""}, 03491 // {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""}, 03492 // {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""}, 03493 {CU_NURBS, "NURBS", 0, "NURBS", ""}, 03494 {0, NULL, 0, NULL, NULL}}; 03495 03496 /* identifiers */ 03497 ot->name= "Set Spline Type"; 03498 ot->description = "Set type of active spline"; 03499 ot->idname= "CURVE_OT_spline_type_set"; 03500 03501 /* api callbacks */ 03502 ot->exec= set_spline_type_exec; 03503 ot->invoke= WM_menu_invoke; 03504 ot->poll= ED_operator_editcurve; 03505 03506 /* flags */ 03507 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03508 03509 /* properties */ 03510 ot->prop= RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type"); 03511 } 03512 03513 /***************** set handle type operator *******************/ 03514 03515 static int set_handle_type_exec(bContext *C, wmOperator *op) 03516 { 03517 Object *obedit= CTX_data_edit_object(C); 03518 ListBase *editnurb= object_editcurve_get(obedit); 03519 03520 sethandlesNurb(editnurb, RNA_enum_get(op->ptr, "type")); 03521 03522 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 03523 DAG_id_tag_update(obedit->data, 0); 03524 03525 return OPERATOR_FINISHED; 03526 } 03527 03528 void CURVE_OT_handle_type_set(wmOperatorType *ot) 03529 { 03530 /* keep in sync with graphkeys_handle_type_items */ 03531 static EnumPropertyItem editcurve_handle_type_items[]= { 03532 {HD_AUTO, "AUTOMATIC", 0, "Automatic", ""}, 03533 {HD_VECT, "VECTOR", 0, "Vector", ""}, 03534 {5, "ALIGNED", 0, "Aligned", ""}, 03535 {6, "FREE_ALIGN", 0, "Free", ""}, 03536 {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""}, 03537 {0, NULL, 0, NULL, NULL}}; 03538 03539 /* identifiers */ 03540 ot->name= "Set Handle Type"; 03541 ot->description = "Set type of handles for selected control points"; 03542 ot->idname= "CURVE_OT_handle_type_set"; 03543 03544 /* api callbacks */ 03545 ot->invoke= WM_menu_invoke; 03546 ot->exec= set_handle_type_exec; 03547 ot->poll= ED_operator_editcurve; 03548 03549 /* flags */ 03550 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03551 03552 /* properties */ 03553 ot->prop= RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); 03554 } 03555 03556 /***************** make segment operator **********************/ 03557 03558 /* ******************** SKINNING LOFTING!!! ******************** */ 03559 03560 static void switchdirection_knots(float *base, int tot) 03561 { 03562 float *fp1, *fp2, *tempf; 03563 int a; 03564 03565 if(base==NULL || tot==0) return; 03566 03567 /* reverse knots */ 03568 a= tot; 03569 fp1= base; 03570 fp2= fp1+(a-1); 03571 a/= 2; 03572 while(fp1!=fp2 && a>0) { 03573 SWAP(float, *fp1, *fp2); 03574 a--; 03575 fp1++; 03576 fp2--; 03577 } 03578 /* and make in increasing order again */ 03579 a= tot; 03580 fp1= base; 03581 fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect"); 03582 while(a--) { 03583 fp2[0]= fabs(fp1[1]-fp1[0]); 03584 fp1++; 03585 fp2++; 03586 } 03587 03588 a= tot-1; 03589 fp1= base; 03590 fp2= tempf; 03591 fp1[0]= 0.0; 03592 fp1++; 03593 while(a--) { 03594 fp1[0]= fp1[-1]+fp2[0]; 03595 fp1++; 03596 fp2++; 03597 } 03598 MEM_freeN(tempf); 03599 } 03600 03601 static void rotate_direction_nurb(Nurb *nu) 03602 { 03603 BPoint *bp1, *bp2, *temp; 03604 int u, v; 03605 03606 SWAP(short, nu->pntsu, nu->pntsv); 03607 SWAP(short, nu->orderu, nu->orderv); 03608 SWAP(short, nu->resolu, nu->resolv); 03609 SWAP(short, nu->flagu, nu->flagv); 03610 03611 SWAP(float *, nu->knotsu, nu->knotsv); 03612 switchdirection_knots(nu->knotsv, KNOTSV(nu) ); 03613 03614 temp= MEM_dupallocN(nu->bp); 03615 bp1= nu->bp; 03616 for(v=0; v<nu->pntsv; v++) { 03617 for(u=0; u<nu->pntsu; u++, bp1++) { 03618 bp2= temp + (nu->pntsu-u-1)*(nu->pntsv) + v; 03619 *bp1= *bp2; 03620 } 03621 } 03622 03623 MEM_freeN(temp); 03624 } 03625 03626 static int is_u_selected(Nurb *nu, int u) 03627 { 03628 BPoint *bp; 03629 int v; 03630 03631 /* what about resolu == 2? */ 03632 bp= nu->bp+u; 03633 for(v=0; v<nu->pntsv-1; v++, bp+=nu->pntsu) { 03634 if(v) if(bp->f1 & SELECT) return 1; 03635 } 03636 03637 return 0; 03638 } 03639 03640 typedef struct NurbSort { 03641 struct NurbSort *next, *prev; 03642 Nurb *nu; 03643 float vec[3]; 03644 } NurbSort; 03645 03646 static ListBase nsortbase= {NULL, NULL}; 03647 /* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */ 03648 03649 static void make_selection_list_nurb(ListBase *editnurb) 03650 { 03651 ListBase nbase= {NULL, NULL}; 03652 NurbSort *nus, *nustest, *headdo, *taildo; 03653 Nurb *nu; 03654 BPoint *bp; 03655 float dist, headdist, taildist; 03656 int a; 03657 03658 for(nu= editnurb->first; nu; nu= nu->next) { 03659 if( isNurbsel(nu) ) { 03660 03661 nus = (NurbSort*)MEM_callocN(sizeof(NurbSort), "sort"); 03662 BLI_addhead(&nbase, nus); 03663 nus->nu= nu; 03664 03665 bp= nu->bp; 03666 a= nu->pntsu; 03667 while(a--) { 03668 add_v3_v3(nus->vec, bp->vec); 03669 bp++; 03670 } 03671 mul_v3_fl(nus->vec, 1.0f/(float)nu->pntsu); 03672 03673 03674 } 03675 } 03676 03677 /* just add the first one */ 03678 nus= nbase.first; 03679 BLI_remlink(&nbase, nus); 03680 BLI_addtail( &nsortbase, nus); 03681 03682 /* now add, either at head or tail, the closest one */ 03683 while(nbase.first) { 03684 03685 headdist= taildist= 1.0e30; 03686 headdo= taildo= NULL; 03687 03688 nustest= nbase.first; 03689 while(nustest) { 03690 dist= len_v3v3(nustest->vec, ((NurbSort *)nsortbase.first)->vec); 03691 03692 if(dist<headdist) { 03693 headdist= dist; 03694 headdo= nustest; 03695 } 03696 dist= len_v3v3(nustest->vec, ((NurbSort *)nsortbase.last)->vec); 03697 03698 if(dist<taildist) { 03699 taildist= dist; 03700 taildo= nustest; 03701 } 03702 nustest= nustest->next; 03703 } 03704 03705 if(headdist<taildist) { 03706 BLI_remlink(&nbase, headdo); 03707 BLI_addhead(&nsortbase, headdo); 03708 } 03709 else { 03710 BLI_remlink(&nbase, taildo); 03711 BLI_addtail(&nsortbase, taildo); 03712 } 03713 } 03714 } 03715 03716 static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu2) 03717 { 03718 BPoint *bp, *bp1, *bp2, *temp; 03719 float len1, len2; 03720 int origu, u, v; 03721 03722 /* first nurbs will be changed to make u = resolu-1 selected */ 03723 /* 2nd nurbs will be changed to make u = 0 selected */ 03724 03725 /* first nurbs: u = resolu-1 selected */ 03726 03727 if( is_u_selected(nu1, nu1->pntsu-1) ); 03728 else { 03729 /* For 2D curves blender uses orderv=0. It doesn't make any sense mathematically. */ 03730 /* but after rotating orderu=0 will be confusing. */ 03731 if (nu1->orderv == 0) nu1->orderv= 1; 03732 03733 rotate_direction_nurb(nu1); 03734 if( is_u_selected(nu1, nu1->pntsu-1) ); 03735 else { 03736 rotate_direction_nurb(nu1); 03737 if( is_u_selected(nu1, nu1->pntsu-1) ); 03738 else { 03739 rotate_direction_nurb(nu1); 03740 if( is_u_selected(nu1, nu1->pntsu-1) ); 03741 else { 03742 /* rotate again, now its OK! */ 03743 if(nu1->pntsv!=1) rotate_direction_nurb(nu1); 03744 return; 03745 } 03746 } 03747 } 03748 } 03749 03750 /* 2nd nurbs: u = 0 selected */ 03751 if( is_u_selected(nu2, 0) ); 03752 else { 03753 if (nu2->orderv == 0) nu2->orderv= 1; 03754 rotate_direction_nurb(nu2); 03755 if( is_u_selected(nu2, 0) ); 03756 else { 03757 rotate_direction_nurb(nu2); 03758 if( is_u_selected(nu2, 0) ); 03759 else { 03760 rotate_direction_nurb(nu2); 03761 if( is_u_selected(nu2, 0) ); 03762 else { 03763 /* rotate again, now its OK! */ 03764 if(nu1->pntsu==1) rotate_direction_nurb(nu1); 03765 if(nu2->pntsv!=1) rotate_direction_nurb(nu2); 03766 return; 03767 } 03768 } 03769 } 03770 } 03771 03772 if( nu1->pntsv != nu2->pntsv ) { 03773 BKE_report(op->reports, RPT_ERROR, "Resolution doesn't match"); 03774 return; 03775 } 03776 03777 /* ok, now nu1 has the rightmost collumn and nu2 the leftmost collumn selected */ 03778 /* maybe we need a 'v' flip of nu2? */ 03779 03780 bp1= nu1->bp+nu1->pntsu-1; 03781 bp2= nu2->bp; 03782 len1= 0.0; 03783 03784 for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2+=nu2->pntsu) { 03785 len1+= len_v3v3(bp1->vec, bp2->vec); 03786 } 03787 03788 bp1= nu1->bp + nu1->pntsu-1; 03789 bp2= nu2->bp + nu2->pntsu*(nu2->pntsv-1); 03790 len2= 0.0; 03791 03792 for(v=0; v<nu1->pntsv; v++, bp1+=nu1->pntsu, bp2-=nu2->pntsu) { 03793 len2+= len_v3v3(bp1->vec, bp2->vec); 03794 } 03795 03796 /* merge */ 03797 origu= nu1->pntsu; 03798 nu1->pntsu+= nu2->pntsu; 03799 if(nu1->orderu<3 && nu1->orderu<nu1->pntsu) nu1->orderu++; 03800 if(nu1->orderv<3 && nu1->orderv<nu1->pntsv) nu1->orderv++; 03801 temp= nu1->bp; 03802 nu1->bp= MEM_mallocN(nu1->pntsu*nu1->pntsv*sizeof(BPoint), "mergeBP"); 03803 03804 bp= nu1->bp; 03805 bp1= temp; 03806 03807 for(v=0; v<nu1->pntsv; v++) { 03808 03809 /* switch direction? */ 03810 if(len1<len2) bp2= nu2->bp + v*nu2->pntsu; 03811 else bp2= nu2->bp + (nu1->pntsv-v-1)*nu2->pntsu; 03812 03813 for(u=0; u<nu1->pntsu; u++, bp++) { 03814 if(u<origu) { 03815 *bp= *bp1; bp1++; 03816 select_bpoint(bp, SELECT, 1, HIDDEN); 03817 } 03818 else { 03819 *bp= *bp2; bp2++; 03820 } 03821 } 03822 } 03823 03824 if(nu1->type == CU_NURBS) { 03825 /* merge knots */ 03826 nurbs_knot_calc_u(nu1); 03827 03828 /* make knots, for merged curved for example */ 03829 nurbs_knot_calc_v(nu1); 03830 } 03831 03832 MEM_freeN(temp); 03833 BLI_remlink(editnurb, nu2); 03834 freeNurb(nu2); 03835 } 03836 03837 static int merge_nurb(bContext *C, wmOperator *op) 03838 { 03839 Object *obedit= CTX_data_edit_object(C); 03840 ListBase *editnurb= object_editcurve_get(obedit); 03841 NurbSort *nus1, *nus2; 03842 int ok= 1; 03843 03844 make_selection_list_nurb(editnurb); 03845 03846 if(nsortbase.first == nsortbase.last) { 03847 BLI_freelistN(&nsortbase); 03848 BKE_report(op->reports, RPT_ERROR, "Too few selections to merge"); 03849 return OPERATOR_CANCELLED; 03850 } 03851 03852 nus1= nsortbase.first; 03853 nus2= nus1->next; 03854 03855 /* resolution match, to avoid uv rotations */ 03856 if(nus1->nu->pntsv==1) { 03857 if(nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsu==nus2->nu->pntsv); 03858 else ok= 0; 03859 } 03860 else if(nus2->nu->pntsv==1) { 03861 if(nus2->nu->pntsu==nus1->nu->pntsu || nus2->nu->pntsu==nus1->nu->pntsv); 03862 else ok= 0; 03863 } 03864 else if( nus1->nu->pntsu==nus2->nu->pntsu || nus1->nu->pntsv==nus2->nu->pntsv); 03865 else if( nus1->nu->pntsu==nus2->nu->pntsv || nus1->nu->pntsv==nus2->nu->pntsu); 03866 else { 03867 ok= 0; 03868 } 03869 03870 if(ok==0) { 03871 BKE_report(op->reports, RPT_ERROR, "Resolution doesn't match"); 03872 BLI_freelistN(&nsortbase); 03873 return OPERATOR_CANCELLED; 03874 } 03875 03876 while(nus2) { 03877 merge_2_nurb(op, editnurb, nus1->nu, nus2->nu); 03878 nus2= nus2->next; 03879 } 03880 03881 BLI_freelistN(&nsortbase); 03882 03883 set_actNurb(obedit, NULL); 03884 03885 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 03886 DAG_id_tag_update(obedit->data, 0); 03887 03888 return OPERATOR_FINISHED; 03889 } 03890 03891 static int make_segment_exec(bContext *C, wmOperator *op) 03892 { 03893 /* joins 2 curves */ 03894 Object *obedit= CTX_data_edit_object(C); 03895 Curve *cu= obedit->data; 03896 ListBase *nubase= object_editcurve_get(obedit); 03897 Nurb *nu, *nu1=NULL, *nu2=NULL; 03898 BPoint *bp; 03899 float *fp, offset; 03900 int a, ok= 0; 03901 03902 /* first decide if this is a surface merge! */ 03903 if(obedit->type==OB_SURF) nu= nubase->first; 03904 else nu= NULL; 03905 03906 while(nu) { 03907 if( isNurbsel(nu) ) { 03908 03909 if(nu->pntsu>1 && nu->pntsv>1) break; 03910 if(isNurbsel_count(cu, nu)>1) break; 03911 if(isNurbsel_count(cu, nu)==1) { 03912 /* only 1 selected, not first or last, a little complex, but intuitive */ 03913 if(nu->pntsv==1) { 03914 if( (nu->bp->f1 & SELECT) || ((nu->bp+nu->pntsu-1)->f1 & SELECT)); 03915 else break; 03916 } 03917 } 03918 } 03919 nu= nu->next; 03920 } 03921 03922 if(nu) 03923 return merge_nurb(C, op); 03924 03925 /* find both nurbs and points, nu1 will be put behind nu2 */ 03926 for(nu= nubase->first; nu; nu= nu->next) { 03927 if(nu->pntsu == 1) 03928 nu->flagu&= ~CU_NURB_CYCLIC; 03929 03930 if((nu->flagu & CU_NURB_CYCLIC)==0) { /* not cyclic */ 03931 if(nu->type == CU_BEZIER) { 03932 if(nu1==NULL) { 03933 if( BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) nu1= nu; 03934 else { 03935 if( BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu-1])) ) { 03936 nu1= nu; 03937 switchdirectionNurb(nu); 03938 keyData_switchDirectionNurb(cu, nu); 03939 } 03940 } 03941 } 03942 else if(nu2==NULL) { 03943 if( BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) { 03944 nu2= nu; 03945 switchdirectionNurb(nu); 03946 keyData_switchDirectionNurb(cu, nu); 03947 } 03948 else { 03949 if( BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu-1])) ) { 03950 nu2= nu; 03951 } 03952 } 03953 } 03954 else break; 03955 } 03956 else if(nu->pntsv==1) { 03957 bp= nu->bp; 03958 if(nu1==NULL) { 03959 if( bp->f1 & SELECT) nu1= nu; 03960 else { 03961 bp= bp+(nu->pntsu-1); 03962 if( bp->f1 & SELECT ) { 03963 nu1= nu; 03964 switchdirectionNurb(nu); 03965 keyData_switchDirectionNurb(cu, nu); 03966 } 03967 } 03968 } 03969 else if(nu2==NULL) { 03970 if( bp->f1 & SELECT ) { 03971 nu2= nu; 03972 switchdirectionNurb(nu); 03973 keyData_switchDirectionNurb(cu, nu); 03974 } 03975 else { 03976 bp= bp+(nu->pntsu-1); 03977 if( bp->f1 & SELECT ) { 03978 nu2= nu; 03979 } 03980 } 03981 } 03982 else break; 03983 } 03984 } 03985 } 03986 03987 if((nu1 && nu2) && (nu1!=nu2)) { 03988 if( nu1->type==nu2->type) { 03989 if(nu1->type == CU_BEZIER) { 03990 BezTriple *bezt = 03991 (BezTriple*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BezTriple), "addsegmentN"); 03992 ED_curve_beztcpy(cu->editnurb, bezt, nu2->bezt, nu2->pntsu); 03993 ED_curve_beztcpy(cu->editnurb, bezt+nu2->pntsu, nu1->bezt, nu1->pntsu); 03994 03995 MEM_freeN(nu1->bezt); 03996 nu1->bezt= bezt; 03997 nu1->pntsu+= nu2->pntsu; 03998 BLI_remlink(nubase, nu2); 03999 freeNurb(nu2); nu2= NULL; 04000 calchandlesNurb(nu1); 04001 } 04002 else { 04003 bp = 04004 (BPoint*)MEM_mallocN((nu1->pntsu+nu2->pntsu) * sizeof(BPoint), "addsegmentN2"); 04005 ED_curve_bpcpy(cu->editnurb, bp, nu2->bp, nu2->pntsu); 04006 ED_curve_bpcpy(cu->editnurb, bp+nu2->pntsu, nu1->bp, nu1->pntsu); 04007 MEM_freeN(nu1->bp); 04008 nu1->bp= bp; 04009 04010 a= nu1->pntsu+nu1->orderu; 04011 04012 nu1->pntsu+= nu2->pntsu; 04013 BLI_remlink(nubase, nu2); 04014 04015 /* now join the knots */ 04016 if(nu1->type == CU_NURBS) { 04017 if(nu1->knotsu==NULL) { 04018 nurbs_knot_calc_u(nu1); 04019 } 04020 else { 04021 fp= MEM_mallocN(sizeof(float)*KNOTSU(nu1), "addsegment3"); 04022 memcpy(fp, nu1->knotsu, sizeof(float)*a); 04023 MEM_freeN(nu1->knotsu); 04024 nu1->knotsu= fp; 04025 04026 04027 offset= nu1->knotsu[a-1] + 1.0f; 04028 fp= nu1->knotsu+a; 04029 for(a=0; a<nu2->pntsu; a++, fp++) { 04030 if(nu2->knotsu) 04031 *fp= offset+nu2->knotsu[a+1]; 04032 else 04033 *fp = offset; 04034 } 04035 } 04036 } 04037 freeNurb(nu2); nu2= NULL; 04038 } 04039 04040 set_actNurb(obedit, nu1); /* for selected */ 04041 ok= 1; 04042 } 04043 } else if(nu1 && !nu2) { 04044 if(!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu>1) { 04045 if (nu1->type == CU_BEZIER && BEZSELECTED_HIDDENHANDLES(cu, nu1->bezt) && 04046 BEZSELECTED_HIDDENHANDLES(cu, nu1->bezt+(nu1->pntsu-1))) { 04047 nu1->flagu|= CU_NURB_CYCLIC; 04048 calchandlesNurb(nu1); 04049 ok= 1; 04050 } else if (nu1->type == CU_NURBS && nu1->bp->f1&SELECT && (nu1->bp+(nu1->pntsu-1))->f1&SELECT) { 04051 nu1->flagu|= CU_NURB_CYCLIC; 04052 nurbs_knot_calc_u(nu1); 04053 ok= 1; 04054 } 04055 } 04056 } 04057 04058 if(!ok) { 04059 BKE_report(op->reports, RPT_ERROR, "Can't make segment"); 04060 return OPERATOR_CANCELLED; 04061 } 04062 04063 if(ED_curve_updateAnimPaths(obedit)) 04064 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 04065 04066 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 04067 DAG_id_tag_update(obedit->data, 0); 04068 04069 return OPERATOR_FINISHED; 04070 } 04071 04072 void CURVE_OT_make_segment(wmOperatorType *ot) 04073 { 04074 /* identifiers */ 04075 ot->name= "Make Segment"; 04076 ot->idname= "CURVE_OT_make_segment"; 04077 04078 /* api callbacks */ 04079 ot->exec= make_segment_exec; 04080 ot->poll= ED_operator_editsurfcurve; 04081 04082 /* flags */ 04083 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04084 } 04085 04086 /***************** pick select from 3d view **********************/ 04087 04088 int mouse_nurb(bContext *C, const int mval[2], int extend) 04089 { 04090 Object *obedit= CTX_data_edit_object(C); 04091 Curve *cu= obedit->data; 04092 ListBase *editnurb= object_editcurve_get(obedit); 04093 ViewContext vc; 04094 Nurb *nu; 04095 BezTriple *bezt=NULL; 04096 BPoint *bp=NULL; 04097 int location[2]; 04098 short hand; 04099 04100 view3d_operator_needs_opengl(C); 04101 view3d_set_viewcontext(C, &vc); 04102 04103 location[0]= mval[0]; 04104 location[1]= mval[1]; 04105 hand= findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp); 04106 04107 if(bezt || bp) { 04108 if(extend==0) { 04109 04110 setflagsNurb(editnurb, 0); 04111 04112 if(bezt) { 04113 04114 if(hand==1) { 04115 select_beztriple(bezt, SELECT, 1, HIDDEN); 04116 cu->lastsel= bezt; 04117 } else { 04118 if(hand==0) bezt->f1|= SELECT; 04119 else bezt->f3|= SELECT; 04120 04121 cu->lastsel= NULL; 04122 } 04123 } 04124 else { 04125 cu->lastsel= bp; 04126 select_bpoint(bp, SELECT, 1, HIDDEN); 04127 } 04128 04129 } 04130 else { 04131 if(bezt) { 04132 if(hand==1) { 04133 if(bezt->f2 & SELECT) { 04134 select_beztriple(bezt, DESELECT, 1, HIDDEN); 04135 if (bezt == cu->lastsel) cu->lastsel = NULL; 04136 } else { 04137 select_beztriple(bezt, SELECT, 1, HIDDEN); 04138 cu->lastsel= bezt; 04139 } 04140 } else if(hand==0) { 04141 bezt->f1 ^= SELECT; 04142 } else { 04143 bezt->f3 ^= SELECT; 04144 } 04145 } 04146 else { 04147 if(bp->f1 & SELECT) { 04148 select_bpoint(bp, DESELECT, 1, HIDDEN); 04149 if (cu->lastsel == bp) cu->lastsel = NULL; 04150 } else { 04151 select_bpoint(bp, SELECT, 1, HIDDEN); 04152 cu->lastsel= bp; 04153 } 04154 } 04155 04156 } 04157 04158 if(nu!=get_actNurb(obedit)) 04159 set_actNurb(obedit, nu); 04160 04161 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 04162 04163 return 1; 04164 } 04165 04166 return 0; 04167 } 04168 04169 /******************** spin operator ***********************/ 04170 04171 /* 'cent' is in object space and 'dvec' in worldspace. 04172 */ 04173 static int spin_nurb(float viewmat[][4], Object *obedit, float *axis, float *cent) 04174 { 04175 Curve *cu= (Curve*)obedit->data; 04176 ListBase *editnurb= object_editcurve_get(obedit); 04177 Nurb *nu; 04178 float si,phi,n[3],q[4],cmat[3][3],tmat[3][3],imat[3][3]; 04179 float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3]; 04180 float persmat[3][3], persinv[3][3]; 04181 short a,ok, changed= 0; 04182 04183 copy_m3_m4(persmat, viewmat); 04184 invert_m3_m3(persinv, persmat); 04185 04186 /* imat and center and size */ 04187 copy_m3_m4(bmat, obedit->obmat); 04188 invert_m3_m3(imat, bmat); 04189 04190 normalize_v3_v3(n, axis); 04191 04192 phi= M_PI/8.0; 04193 q[0]= cos(phi); 04194 si= sin(phi); 04195 q[1]= n[0]*si; 04196 q[2]= n[1]*si; 04197 q[3]= n[2]*si; 04198 quat_to_mat3( cmat,q); 04199 mul_m3_m3m3(tmat, cmat, bmat); 04200 mul_m3_m3m3(rotmat, imat, tmat); 04201 04202 unit_m3(scalemat1); 04203 scalemat1[0][0]= M_SQRT2; 04204 scalemat1[1][1]= M_SQRT2; 04205 04206 mul_m3_m3m3(tmat,persmat,bmat); 04207 mul_m3_m3m3(cmat,scalemat1,tmat); 04208 mul_m3_m3m3(tmat,persinv,cmat); 04209 mul_m3_m3m3(scalemat1,imat,tmat); 04210 04211 unit_m3(scalemat2); 04212 scalemat2[0][0]/= (float)M_SQRT2; 04213 scalemat2[1][1]/= (float)M_SQRT2; 04214 04215 mul_m3_m3m3(tmat,persmat,bmat); 04216 mul_m3_m3m3(cmat,scalemat2,tmat); 04217 mul_m3_m3m3(tmat,persinv,cmat); 04218 mul_m3_m3m3(scalemat2,imat,tmat); 04219 04220 ok= 1; 04221 04222 for(a=0;a<7;a++) { 04223 ok= extrudeflagNurb(cu->editnurb, 1); 04224 04225 if(ok==0) 04226 return changed; 04227 04228 changed= 1; 04229 04230 rotateflagNurb(editnurb, SELECT, cent, rotmat); 04231 04232 if( (a & SELECT)==0 ) { 04233 rotateflagNurb(editnurb, SELECT, cent, scalemat1); 04234 weightflagNurb(editnurb, SELECT, 0.25*M_SQRT2); 04235 } 04236 else { 04237 rotateflagNurb(editnurb, SELECT, cent, scalemat2); 04238 weightflagNurb(editnurb, SELECT, 4.0/M_SQRT2); 04239 } 04240 } 04241 04242 if(ok) { 04243 for(nu= editnurb->first; nu; nu= nu->next) { 04244 if(isNurbsel(nu)) { 04245 nu->orderv= 4; 04246 nu->flagv |= CU_NURB_CYCLIC; 04247 nurbs_knot_calc_v(nu); 04248 } 04249 } 04250 } 04251 04252 return changed; 04253 } 04254 04255 static int spin_exec(bContext *C, wmOperator *op) 04256 { 04257 Object *obedit= CTX_data_edit_object(C); 04258 RegionView3D *rv3d= ED_view3d_context_rv3d(C); 04259 float cent[3], axis[3], viewmat[4][4]; 04260 04261 RNA_float_get_array(op->ptr, "center", cent); 04262 RNA_float_get_array(op->ptr, "axis", axis); 04263 04264 invert_m4_m4(obedit->imat, obedit->obmat); 04265 mul_m4_v3(obedit->imat, cent); 04266 04267 if(rv3d) 04268 copy_m4_m4(viewmat, rv3d->viewmat); 04269 else 04270 unit_m4(viewmat); 04271 04272 if(!spin_nurb(viewmat, obedit, axis, cent)) { 04273 BKE_report(op->reports, RPT_ERROR, "Can't spin"); 04274 return OPERATOR_CANCELLED; 04275 } 04276 04277 if(ED_curve_updateAnimPaths(obedit)) 04278 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 04279 04280 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 04281 DAG_id_tag_update(obedit->data, 0); 04282 04283 return OPERATOR_FINISHED; 04284 } 04285 04286 static int spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 04287 { 04288 Scene *scene = CTX_data_scene(C); 04289 View3D *v3d = CTX_wm_view3d(C); 04290 RegionView3D *rv3d= ED_view3d_context_rv3d(C); 04291 float axis[3]= {0.0f, 0.0f, 1.0f}; 04292 04293 if(rv3d) 04294 copy_v3_v3(axis, rv3d->viewinv[2]); 04295 04296 RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); 04297 RNA_float_set_array(op->ptr, "axis", axis); 04298 04299 return spin_exec(C, op); 04300 } 04301 04302 void CURVE_OT_spin(wmOperatorType *ot) 04303 { 04304 /* identifiers */ 04305 ot->name= "Spin"; 04306 ot->idname= "CURVE_OT_spin"; 04307 04308 /* api callbacks */ 04309 ot->exec= spin_exec; 04310 ot->invoke = spin_invoke; 04311 ot->poll= ED_operator_editsurf; 04312 04313 /* flags */ 04314 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04315 04316 RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); 04317 RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); 04318 } 04319 04320 /***************** add vertex operator **********************/ 04321 04322 static int addvert_Nurb(bContext *C, short mode, float location[3]) 04323 { 04324 Object *obedit= CTX_data_edit_object(C); 04325 Curve *cu= (Curve*)obedit->data; 04326 EditNurb *editnurb= cu->editnurb; 04327 Nurb *nu, *newnu= NULL; 04328 BezTriple *bezt, *newbezt = NULL; 04329 BPoint *bp, *newbp = NULL; 04330 float imat[4][4], temp[3]; 04331 int ok= 0; 04332 04333 invert_m4_m4(imat, obedit->obmat); 04334 04335 findselectedNurbvert(&editnurb->nurbs, &nu, &bezt, &bp); 04336 04337 if ((nu == NULL) || (nu->type==CU_BEZIER && bezt==NULL) || (nu->type!=CU_BEZIER && bp==NULL)) { 04338 if(mode!='e') { 04339 if(cu->actnu >= 0) 04340 nu= BLI_findlink(&editnurb->nurbs, cu->actnu); 04341 04342 if(!nu || nu->type==CU_BEZIER) { 04343 newbezt= (BezTriple*)MEM_callocN(sizeof(BezTriple), "addvert_Nurb"); 04344 newbezt->radius= 1; 04345 newbezt->alfa= 0; 04346 BEZ_SEL(newbezt); 04347 newbezt->h2= newbezt->h1= HD_AUTO; 04348 04349 newnu= (Nurb*)MEM_callocN(sizeof(Nurb), "addvert_Nurb newnu"); 04350 if(!nu) { 04351 /* no selected sement -- create new one which is BEZIER tpye 04352 type couldn't be determined from Curve bt could be changed 04353 in the future, so shouldn't make much headache */ 04354 newnu->type= CU_BEZIER; 04355 newnu->resolu= cu->resolu; 04356 newnu->flag |= CU_SMOOTH; 04357 } else memcpy(newnu, nu, sizeof(Nurb)); 04358 04359 BLI_addtail(&editnurb->nurbs, newnu); 04360 set_actNurb(obedit, newnu); 04361 newnu->bezt= newbezt; 04362 newnu->pntsu= 1; 04363 04364 temp[0] = 1; 04365 temp[1] = 0; 04366 temp[2] = 0; 04367 04368 copy_v3_v3(newbezt->vec[1], location); 04369 sub_v3_v3v3(newbezt->vec[0], newbezt->vec[1], temp); 04370 add_v3_v3v3(newbezt->vec[2], newbezt->vec[1], temp); 04371 04372 mul_m4_v3(imat, newbezt->vec[0]); 04373 mul_m4_v3(imat, newbezt->vec[1]); 04374 mul_m4_v3(imat, newbezt->vec[2]); 04375 04376 ok= 1; 04377 nu= newnu; 04378 } else if(nu->pntsv == 1) { 04379 newbp= (BPoint*)MEM_callocN(sizeof(BPoint), "addvert_Nurb5"); 04380 newbp->radius= 1; 04381 newbp->alfa= 0; 04382 newbp->f1|= SELECT; 04383 cu->lastsel= newbp; 04384 04385 newnu= (Nurb*)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu"); 04386 memcpy(newnu, nu, sizeof(Nurb)); 04387 BLI_addtail(&editnurb->nurbs, newnu); 04388 set_actNurb(obedit, newnu); 04389 newnu->bp= newbp; 04390 newnu->orderu= 2; 04391 newnu->pntsu= 1; 04392 04393 mul_v3_m4v3(newbp->vec, imat, location); 04394 newbp->vec[3]= 1.0; 04395 04396 newnu->knotsu= newnu->knotsv= NULL; 04397 nurbs_knot_calc_u(newnu); 04398 04399 ok= 1; 04400 nu= newnu; 04401 } 04402 04403 } 04404 04405 if(!ok) 04406 return OPERATOR_CANCELLED; 04407 } 04408 04409 if(!ok && nu->type == CU_BEZIER) { 04410 /* which bezpoint? */ 04411 if(bezt== (nu->bezt+nu->pntsu-1)) { /* last */ 04412 BEZ_DESEL(bezt); 04413 newbezt = 04414 (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb"); 04415 ED_curve_beztcpy(editnurb, newbezt, nu->bezt, nu->pntsu); 04416 *(newbezt+nu->pntsu)= *bezt; 04417 copy_v3_v3(temp, bezt->vec[1]); 04418 MEM_freeN(nu->bezt); 04419 nu->bezt= newbezt; 04420 newbezt+= nu->pntsu; 04421 BEZ_SEL(newbezt); 04422 cu->lastsel= newbezt; 04423 newbezt->h2= newbezt->h1; 04424 bezt= nu->bezt+nu->pntsu-1; 04425 ok= 1; 04426 } 04427 else if(bezt== nu->bezt) { /* first */ 04428 BEZ_DESEL(bezt); 04429 newbezt = 04430 (BezTriple*)MEM_callocN((nu->pntsu+1) * sizeof(BezTriple), "addvert_Nurb"); 04431 ED_curve_beztcpy(editnurb, newbezt+1, bezt, nu->pntsu); 04432 *newbezt= *bezt; 04433 BEZ_SEL(newbezt); 04434 cu->lastsel= newbezt; 04435 newbezt->h2= newbezt->h1; 04436 copy_v3_v3(temp, bezt->vec[1]); 04437 MEM_freeN(nu->bezt); 04438 nu->bezt= newbezt; 04439 bezt= newbezt+1; 04440 ok= 1; 04441 } 04442 else if(mode!='e') { 04443 BEZ_DESEL(bezt); 04444 newbezt= (BezTriple*)MEM_callocN(sizeof(BezTriple), "addvert_Nurb"); 04445 *newbezt= *bezt; 04446 BEZ_SEL(newbezt); 04447 newbezt->h2= newbezt->h1; 04448 copy_v3_v3(temp, bezt->vec[1]); 04449 04450 newnu= (Nurb*)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu"); 04451 memcpy(newnu, nu, sizeof(Nurb)); 04452 BLI_addtail(&editnurb->nurbs, newnu); 04453 set_actNurb(obedit, newnu); 04454 newnu->bezt= newbezt; 04455 newnu->pntsu= 1; 04456 04457 cu->lastsel= newbezt; 04458 04459 bezt= newbezt; 04460 ok= 1; 04461 } 04462 else bezt= NULL; 04463 04464 if(bezt) { 04465 if(!newnu) nu->pntsu++; 04466 04467 if(mode=='e') { 04468 copy_v3_v3(newbezt->vec[0], bezt->vec[0]); 04469 copy_v3_v3(newbezt->vec[1], bezt->vec[1]); 04470 copy_v3_v3(newbezt->vec[2], bezt->vec[2]); 04471 } 04472 else { 04473 mul_v3_m4v3(newbezt->vec[1], imat, location); 04474 sub_v3_v3v3(temp, newbezt->vec[1],temp); 04475 add_v3_v3v3(newbezt->vec[0], bezt->vec[0],temp); 04476 add_v3_v3v3(newbezt->vec[2], bezt->vec[2],temp); 04477 04478 if(newnu) calchandlesNurb(newnu); 04479 else calchandlesNurb(nu); 04480 } 04481 } 04482 } 04483 else if(!ok && nu->pntsv==1) { 04484 /* which b-point? */ 04485 if(bp== (nu->bp+nu->pntsu-1)) { /* last */ 04486 bp->f1= 0; 04487 newbp = 04488 (BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb4"); 04489 ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); 04490 *(newbp+nu->pntsu)= *bp; 04491 MEM_freeN(nu->bp); 04492 nu->bp= newbp; 04493 newbp+= nu->pntsu; 04494 newbp->f1|= SELECT; 04495 cu->lastsel= newbp; 04496 bp= newbp - 1; 04497 ok= 1; 04498 } 04499 else if(bp== nu->bp) { /* first */ 04500 bp->f1= 0; 04501 newbp = 04502 (BPoint*)MEM_callocN((nu->pntsu+1) * sizeof(BPoint), "addvert_Nurb3"); 04503 ED_curve_bpcpy(editnurb, newbp+1, bp, nu->pntsu); 04504 *newbp= *bp; 04505 newbp->f1|= SELECT; 04506 cu->lastsel= newbp; 04507 MEM_freeN(nu->bp); 04508 nu->bp= newbp; 04509 bp= newbp + 1; 04510 ok= 1; 04511 } 04512 else if(mode!='e') { 04513 bp->f1= 0; 04514 newbp= (BPoint*)MEM_callocN(sizeof(BPoint), "addvert_Nurb5"); 04515 *newbp= *bp; 04516 newbp->f1|= SELECT; 04517 cu->lastsel= newbp; 04518 04519 newnu= (Nurb*)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu"); 04520 memcpy(newnu, nu, sizeof(Nurb)); 04521 BLI_addtail(&editnurb->nurbs, newnu); 04522 set_actNurb(obedit, newnu); 04523 newnu->bp= newbp; 04524 newnu->orderu= 2; 04525 newnu->pntsu= 1; 04526 newnu->knotsu= newnu->knotsv= NULL; 04527 04528 bp= newbp; 04529 ok= 1; 04530 } 04531 else bp= NULL; 04532 04533 if(bp) { 04534 if(mode=='e') { 04535 copy_v3_v3(newbp->vec, bp->vec); 04536 } 04537 else { 04538 mul_v3_m4v3(newbp->vec, imat, location); 04539 newbp->vec[3]= 1.0; 04540 04541 if(!newnu && nu->orderu<4 && nu->orderu<=nu->pntsu) 04542 nu->orderu++; 04543 } 04544 04545 if(!newnu) { 04546 nu->pntsu++; 04547 nurbs_knot_calc_u(nu); 04548 } else nurbs_knot_calc_u(newnu); 04549 } 04550 } 04551 04552 if(ok) { 04553 test2DNurb(nu); 04554 04555 if(ED_curve_updateAnimPaths(obedit)) 04556 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 04557 04558 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 04559 DAG_id_tag_update(obedit->data, 0); 04560 04561 return OPERATOR_FINISHED; 04562 } 04563 04564 return OPERATOR_CANCELLED; 04565 } 04566 04567 static int add_vertex_exec(bContext *C, wmOperator *op) 04568 { 04569 float location[3]; 04570 04571 RNA_float_get_array(op->ptr, "location", location); 04572 return addvert_Nurb(C, 0, location); 04573 } 04574 04575 static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) 04576 { 04577 RegionView3D *rv3d= CTX_wm_region_view3d(C); 04578 04579 if(rv3d && !RNA_struct_property_is_set(op->ptr, "location")) { 04580 Curve *cu; 04581 ViewContext vc; 04582 float location[3]; 04583 04584 Nurb *nu; 04585 BezTriple *bezt; 04586 BPoint *bp; 04587 04588 view3d_set_viewcontext(C, &vc); 04589 04590 cu= vc.obedit->data; 04591 04592 findselectedNurbvert(&cu->editnurb->nurbs, &nu, &bezt, &bp); 04593 04594 if(bezt) { 04595 mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]); 04596 } 04597 else if (bp) { 04598 mul_v3_m4v3(location, vc.obedit->obmat, bp->vec); 04599 } 04600 else { 04601 copy_v3_v3(location, give_cursor(vc.scene, vc.v3d)); 04602 } 04603 04604 view3d_get_view_aligned_coordinate(&vc, location, event->mval, TRUE); 04605 RNA_float_set_array(op->ptr, "location", location); 04606 } 04607 04608 return add_vertex_exec(C, op); 04609 } 04610 04611 void CURVE_OT_vertex_add(wmOperatorType *ot) 04612 { 04613 /* identifiers */ 04614 ot->name= "Add Vertex"; 04615 ot->idname= "CURVE_OT_vertex_add"; 04616 04617 /* api callbacks */ 04618 ot->exec= add_vertex_exec; 04619 ot->invoke= add_vertex_invoke; 04620 ot->poll= ED_operator_editcurve; 04621 04622 /* flags */ 04623 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04624 04625 /* properties */ 04626 RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location to add new vertex at", -1e4, 1e4); 04627 } 04628 04629 /***************** extrude operator **********************/ 04630 04631 static int extrude_exec(bContext *C, wmOperator *UNUSED(op)) 04632 { 04633 Object *obedit= CTX_data_edit_object(C); 04634 Curve *cu= obedit->data; 04635 EditNurb *editnurb= cu->editnurb; 04636 Nurb *nu; 04637 04638 /* first test: curve? */ 04639 for(nu= editnurb->nurbs.first; nu; nu= nu->next) 04640 if(nu->pntsv==1 && isNurbsel_count(cu, nu)==1) 04641 break; 04642 04643 if(obedit->type==OB_CURVE || nu) { 04644 addvert_Nurb(C, 'e', NULL); 04645 } 04646 else { 04647 if(extrudeflagNurb(editnurb, 1)) { /* '1'= flag */ 04648 if(ED_curve_updateAnimPaths(obedit)) 04649 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 04650 04651 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 04652 DAG_id_tag_update(obedit->data, 0); 04653 } 04654 } 04655 04656 return OPERATOR_FINISHED; 04657 } 04658 04659 void CURVE_OT_extrude(wmOperatorType *ot) 04660 { 04661 /* identifiers */ 04662 ot->name= "Extrude"; 04663 ot->description = "Extrude selected control point(s) and move"; 04664 ot->idname= "CURVE_OT_extrude"; 04665 04666 /* api callbacks */ 04667 ot->exec= extrude_exec; 04668 ot->poll= ED_operator_editsurfcurve; 04669 04670 /* flags */ 04671 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04672 04673 /* to give to transform */ 04674 RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); 04675 } 04676 04677 /***************** make cyclic operator **********************/ 04678 04679 static int toggle_cyclic_exec(bContext *C, wmOperator *op) 04680 { 04681 Object *obedit= CTX_data_edit_object(C); 04682 Curve *cu= obedit->data; 04683 ListBase *editnurb= object_editcurve_get(obedit); 04684 Nurb *nu; 04685 BezTriple *bezt; 04686 BPoint *bp; 04687 int a, direction= RNA_enum_get(op->ptr, "direction"); 04688 04689 for(nu= editnurb->first; nu; nu= nu->next) { 04690 if( nu->pntsu>1 || nu->pntsv>1) { 04691 if(nu->type == CU_POLY) { 04692 a= nu->pntsu; 04693 bp= nu->bp; 04694 while(a--) { 04695 if( bp->f1 & SELECT ) { 04696 nu->flagu ^= CU_NURB_CYCLIC; 04697 break; 04698 } 04699 bp++; 04700 } 04701 } 04702 else if(nu->type == CU_BEZIER) { 04703 a= nu->pntsu; 04704 bezt= nu->bezt; 04705 while(a--) { 04706 if( BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { 04707 nu->flagu ^= CU_NURB_CYCLIC; 04708 break; 04709 } 04710 bezt++; 04711 } 04712 calchandlesNurb(nu); 04713 } 04714 else if(nu->pntsv==1 && nu->type == CU_NURBS) { 04715 if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */ 04716 a= nu->pntsu; 04717 bp= nu->bp; 04718 while(a--) { 04719 if( bp->f1 & SELECT ) { 04720 nu->flagu ^= CU_NURB_CYCLIC; 04721 nurbs_knot_calc_u(nu); /* 1==u type is ignored for cyclic curves */ 04722 break; 04723 } 04724 bp++; 04725 } 04726 } 04727 } 04728 else if(nu->type==CU_NURBS) { 04729 a= nu->pntsu*nu->pntsv; 04730 bp= nu->bp; 04731 while(a--) { 04732 04733 if( bp->f1 & SELECT) { 04734 if(direction==0 && nu->pntsu>1) { 04735 nu->flagu ^= CU_NURB_CYCLIC; 04736 nurbs_knot_calc_u(nu); /* 1==u type is ignored for cyclic curves */ 04737 } 04738 if(direction==1 && nu->pntsv>1) { 04739 nu->flagv ^= CU_NURB_CYCLIC; 04740 nurbs_knot_calc_v(nu); /* 2==v type is ignored for cyclic curves */ 04741 } 04742 break; 04743 } 04744 bp++; 04745 } 04746 04747 } 04748 } 04749 } 04750 04751 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 04752 DAG_id_tag_update(obedit->data, 0); 04753 04754 return OPERATOR_FINISHED; 04755 } 04756 04757 static int toggle_cyclic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 04758 { 04759 Object *obedit= CTX_data_edit_object(C); 04760 ListBase *editnurb= object_editcurve_get(obedit); 04761 uiPopupMenu *pup; 04762 uiLayout *layout; 04763 Nurb *nu; 04764 04765 if(obedit->type == OB_SURF) { 04766 for(nu= editnurb->first; nu; nu= nu->next) { 04767 if(nu->pntsu>1 || nu->pntsv>1) { 04768 if(nu->type==CU_NURBS) { 04769 pup= uiPupMenuBegin(C, "Direction", ICON_NONE); 04770 layout= uiPupMenuLayout(pup); 04771 uiItemsEnumO(layout, op->type->idname, "direction"); 04772 uiPupMenuEnd(C, pup); 04773 return OPERATOR_CANCELLED; 04774 } 04775 } 04776 } 04777 } 04778 04779 return toggle_cyclic_exec(C, op); 04780 } 04781 04782 void CURVE_OT_cyclic_toggle(wmOperatorType *ot) 04783 { 04784 static EnumPropertyItem direction_items[]= { 04785 {0, "CYCLIC_U", 0, "Cyclic U", ""}, 04786 {1, "CYCLIC_V", 0, "Cyclic V", ""}, 04787 {0, NULL, 0, NULL, NULL}}; 04788 04789 /* identifiers */ 04790 ot->name= "Toggle Cyclic"; 04791 ot->description = "Make active spline closed/opened loop"; 04792 ot->idname= "CURVE_OT_cyclic_toggle"; 04793 04794 /* api callbacks */ 04795 ot->exec= toggle_cyclic_exec; 04796 ot->invoke= toggle_cyclic_invoke; 04797 ot->poll= ED_operator_editsurfcurve; 04798 04799 /* flags */ 04800 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04801 04802 /* properties */ 04803 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in"); 04804 } 04805 04806 /***************** select linked operator ******************/ 04807 04808 static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) 04809 { 04810 Object *obedit= CTX_data_edit_object(C); 04811 Curve *cu= (Curve*)obedit->data; 04812 EditNurb *editnurb= cu->editnurb; 04813 ListBase *nurbs= &editnurb->nurbs; 04814 Nurb *nu; 04815 BezTriple *bezt; 04816 BPoint *bp; 04817 int a; 04818 04819 for(nu= nurbs->first; nu; nu= nu->next) { 04820 if(nu->type == CU_BEZIER) { 04821 bezt= nu->bezt; 04822 a= nu->pntsu; 04823 while(a--) { 04824 if( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) { 04825 a= nu->pntsu; 04826 bezt= nu->bezt; 04827 while(a--) { 04828 select_beztriple(bezt, SELECT, 1, VISIBLE); 04829 bezt++; 04830 } 04831 break; 04832 } 04833 bezt++; 04834 } 04835 } 04836 else { 04837 bp= nu->bp; 04838 a= nu->pntsu*nu->pntsv; 04839 while(a--) { 04840 if( bp->f1 & 1 ) { 04841 a= nu->pntsu*nu->pntsv; 04842 bp= nu->bp; 04843 while(a--) { 04844 select_bpoint(bp, SELECT, 1, VISIBLE); 04845 bp++; 04846 } 04847 break; 04848 } 04849 bp++; 04850 } 04851 } 04852 } 04853 04854 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 04855 04856 return OPERATOR_FINISHED; 04857 } 04858 04859 static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 04860 { 04861 return select_linked_exec(C, op); 04862 } 04863 04864 void CURVE_OT_select_linked(wmOperatorType *ot) 04865 { 04866 /* identifiers */ 04867 ot->name= "Select Linked All"; 04868 ot->idname= "CURVE_OT_select_linked"; 04869 04870 /* api callbacks */ 04871 ot->exec= select_linked_exec; 04872 ot->invoke= select_linked_invoke; 04873 ot->poll= ED_operator_editsurfcurve; 04874 04875 /* flags */ 04876 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04877 04878 /* properties */ 04879 } 04880 04881 04882 /***************** select linked pick operator ******************/ 04883 04884 static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) 04885 { 04886 Object *obedit= CTX_data_edit_object(C); 04887 ViewContext vc; 04888 Nurb *nu; 04889 BezTriple *bezt; 04890 BPoint *bp; 04891 int a, deselect; 04892 04893 deselect= RNA_boolean_get(op->ptr, "deselect"); 04894 04895 view3d_operator_needs_opengl(C); 04896 view3d_set_viewcontext(C, &vc); 04897 04898 findnearestNurbvert(&vc, 1, event->mval, &nu, &bezt, &bp); 04899 04900 if(bezt) { 04901 a= nu->pntsu; 04902 bezt= nu->bezt; 04903 while(a--) { 04904 if(deselect) select_beztriple(bezt, DESELECT, 1, VISIBLE); 04905 else select_beztriple(bezt, SELECT, 1, VISIBLE); 04906 bezt++; 04907 } 04908 } 04909 else if(bp) { 04910 a= nu->pntsu*nu->pntsv; 04911 bp= nu->bp; 04912 while(a--) { 04913 if(deselect) select_bpoint(bp, DESELECT, 1, VISIBLE); 04914 else select_bpoint(bp, SELECT, 1, VISIBLE); 04915 bp++; 04916 } 04917 } 04918 04919 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 04920 04921 return OPERATOR_FINISHED; 04922 } 04923 04924 void CURVE_OT_select_linked_pick(wmOperatorType *ot) 04925 { 04926 /* identifiers */ 04927 ot->name= "Select Linked"; 04928 ot->idname= "CURVE_OT_select_linked_pick"; 04929 04930 /* api callbacks */ 04931 ot->invoke= select_linked_pick_invoke; 04932 ot->poll= ED_operator_editsurfcurve_region_view3d; 04933 04934 /* flags */ 04935 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 04936 04937 /* properties */ 04938 RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them"); 04939 } 04940 04941 /***************** select row operator **********************/ 04942 04943 static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) 04944 { 04945 Object *obedit= CTX_data_edit_object(C); 04946 Curve *cu= obedit->data; 04947 ListBase *editnurb= object_editcurve_get(obedit); 04948 static BPoint *last= NULL; 04949 static int direction=0; 04950 Nurb *nu; 04951 BPoint *bp; 04952 int u = 0, v = 0, a, b, ok=0; 04953 04954 if(editnurb->first == NULL) 04955 return OPERATOR_CANCELLED; 04956 if(cu->lastsel==NULL) 04957 return OPERATOR_CANCELLED; 04958 04959 /* find the correct nurb and toggle with u of v */ 04960 for(nu= editnurb->first; nu; nu= nu->next) { 04961 bp= nu->bp; 04962 for(v=0; v<nu->pntsv; v++) { 04963 for(u=0; u<nu->pntsu; u++, bp++) { 04964 if(bp==cu->lastsel) { 04965 if(bp->f1 & SELECT) { 04966 ok= 1; 04967 break; 04968 } 04969 } 04970 } 04971 if(ok) break; 04972 } 04973 04974 if(ok) { 04975 if(last==cu->lastsel) { 04976 direction= 1-direction; 04977 setflagsNurb(editnurb, 0); 04978 } 04979 last= cu->lastsel; 04980 04981 bp= nu->bp; 04982 for(a=0; a<nu->pntsv; a++) { 04983 for(b=0; b<nu->pntsu; b++, bp++) { 04984 if(direction) { 04985 if(a==v) select_bpoint(bp, SELECT, 1, VISIBLE); 04986 } 04987 else { 04988 if(b==u) select_bpoint(bp, SELECT, 1, VISIBLE); 04989 } 04990 } 04991 } 04992 04993 break; 04994 } 04995 } 04996 04997 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 04998 04999 return OPERATOR_FINISHED; 05000 } 05001 05002 void CURVE_OT_select_row(wmOperatorType *ot) 05003 { 05004 /* identifiers */ 05005 ot->name= "Select Control Point Row"; 05006 ot->idname= "CURVE_OT_select_row"; 05007 05008 /* api callbacks */ 05009 ot->exec= select_row_exec; 05010 ot->poll= ED_operator_editsurf; 05011 05012 /* flags */ 05013 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05014 } 05015 05016 /***************** select next operator **********************/ 05017 05018 static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) 05019 { 05020 Object *obedit= CTX_data_edit_object(C); 05021 ListBase *editnurb= object_editcurve_get(obedit); 05022 05023 select_adjacent_cp(editnurb, 1, 0, SELECT); 05024 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05025 05026 return OPERATOR_FINISHED; 05027 } 05028 05029 void CURVE_OT_select_next(wmOperatorType *ot) 05030 { 05031 /* identifiers */ 05032 ot->name= "Select Next"; 05033 ot->idname= "CURVE_OT_select_next"; 05034 05035 /* api callbacks */ 05036 ot->exec= select_next_exec; 05037 ot->poll= ED_operator_editcurve; 05038 05039 /* flags */ 05040 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05041 } 05042 05043 /***************** select previous operator **********************/ 05044 05045 static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) 05046 { 05047 Object *obedit= CTX_data_edit_object(C); 05048 ListBase *editnurb= object_editcurve_get(obedit); 05049 05050 select_adjacent_cp(editnurb, -1, 0, SELECT); 05051 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05052 05053 return OPERATOR_FINISHED; 05054 } 05055 05056 void CURVE_OT_select_previous(wmOperatorType *ot) 05057 { 05058 /* identifiers */ 05059 ot->name= "Select Previous"; 05060 ot->idname= "CURVE_OT_select_previous"; 05061 05062 /* api callbacks */ 05063 ot->exec= select_previous_exec; 05064 ot->poll= ED_operator_editcurve; 05065 05066 /* flags */ 05067 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05068 } 05069 05070 /***************** select more operator **********************/ 05071 05072 static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) 05073 { 05074 Object *obedit= CTX_data_edit_object(C); 05075 ListBase *editnurb= object_editcurve_get(obedit); 05076 Nurb *nu; 05077 BPoint *bp, *tempbp; 05078 int a; 05079 short sel= 0; 05080 short *selbpoints; 05081 05082 /* note that NURBS surface is a special case because we mimic */ 05083 /* the behaviour of "select more" of mesh tools. */ 05084 /* The algorithm is designed to work in planar cases so it */ 05085 /* may not be optimal always (example: end of NURBS sphere) */ 05086 if(obedit->type==OB_SURF) { 05087 for(nu= editnurb->first; nu; nu= nu->next) { 05088 a= nu->pntsu*nu->pntsv; 05089 bp= nu->bp; 05090 selbpoints= MEM_callocN(sizeof(short)*a-nu->pntsu, "selectlist"); 05091 while(a > 0) { 05092 if((selbpoints[a]!=1) && (bp->hide==0) && (bp->f1 & SELECT)) { 05093 /* upper control point */ 05094 if(a%nu->pntsu != 0) { 05095 tempbp= bp-1; 05096 if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); 05097 } 05098 05099 /* left control point. select only if it is not selected already */ 05100 if(a-nu->pntsu > 0) { 05101 sel= 0; 05102 tempbp= bp+nu->pntsu; 05103 if(!(tempbp->f1 & SELECT)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); 05104 /* make sure selected bpoint is discarded */ 05105 if(sel == 1) selbpoints[a-nu->pntsu]= 1; 05106 } 05107 05108 /* right control point */ 05109 if(a+nu->pntsu < nu->pntsu*nu->pntsv) { 05110 tempbp= bp-nu->pntsu; 05111 if(!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); 05112 } 05113 05114 /* lower control point. skip next bp in case selection was made */ 05115 if(a%nu->pntsu != 1) { 05116 sel= 0; 05117 tempbp= bp+1; 05118 if(!(tempbp->f1 & 1)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); 05119 if(sel) { 05120 bp++; 05121 a--; 05122 } 05123 } 05124 } 05125 05126 bp++; 05127 a--; 05128 } 05129 05130 MEM_freeN(selbpoints); 05131 } 05132 } 05133 else { 05134 select_adjacent_cp(editnurb, 1, 0, SELECT); 05135 select_adjacent_cp(editnurb, -1, 0, SELECT); 05136 } 05137 05138 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05139 05140 return OPERATOR_FINISHED; 05141 } 05142 05143 void CURVE_OT_select_more(wmOperatorType *ot) 05144 { 05145 /* identifiers */ 05146 ot->name= "Select More"; 05147 ot->idname= "CURVE_OT_select_more"; 05148 05149 /* api callbacks */ 05150 ot->exec= select_more_exec; 05151 ot->poll= ED_operator_editsurfcurve; 05152 05153 /* flags */ 05154 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05155 } 05156 05157 /******************** select less operator *****************/ 05158 05159 /* basic method: deselect if control point doesn't have all neighbours selected */ 05160 static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) 05161 { 05162 Object *obedit= CTX_data_edit_object(C); 05163 ListBase *editnurb= object_editcurve_get(obedit); 05164 Nurb *nu; 05165 BPoint *bp; 05166 BezTriple *bezt; 05167 int a; 05168 short sel= 0, lastsel= 0; 05169 short *selbpoints; 05170 05171 if(obedit->type==OB_SURF) { 05172 for(nu= editnurb->first; nu; nu= nu->next) { 05173 a= nu->pntsu*nu->pntsv; 05174 bp= nu->bp; 05175 selbpoints= MEM_callocN(sizeof(short)*a, "selectlist"); 05176 while(a--) { 05177 if((bp->hide==0) && (bp->f1 & SELECT)) { 05178 sel= 0; 05179 05180 /* check if neighbours have been selected */ 05181 /* edges of surface are an exception */ 05182 if((a+1)%nu->pntsu==0) sel++; 05183 else { 05184 bp--; 05185 if((selbpoints[a+1]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++; 05186 bp++; 05187 } 05188 05189 if((a+1)%nu->pntsu==1) sel++; 05190 else { 05191 bp++; 05192 if((bp->hide==0) && (bp->f1 & SELECT)) sel++; 05193 bp--; 05194 } 05195 05196 if(a+1 > nu->pntsu*nu->pntsv-nu->pntsu) sel++; 05197 else { 05198 bp-=nu->pntsu; 05199 if((selbpoints[a+nu->pntsu]==1) || ((bp->hide==0) && (bp->f1 & SELECT))) sel++; 05200 bp+=nu->pntsu; 05201 } 05202 05203 if(a < nu->pntsu) sel++; 05204 else { 05205 bp+=nu->pntsu; 05206 if((bp->hide==0) && (bp->f1 & SELECT)) sel++; 05207 bp-=nu->pntsu; 05208 } 05209 05210 if(sel!=4) { 05211 select_bpoint(bp, DESELECT, 1, VISIBLE); 05212 selbpoints[a]= 1; 05213 } 05214 } 05215 else lastsel= 0; 05216 05217 bp++; 05218 } 05219 05220 MEM_freeN(selbpoints); 05221 } 05222 } 05223 else { 05224 for(nu= editnurb->first; nu; nu= nu->next) { 05225 lastsel=0; 05226 /* check what type of curve/nurb it is */ 05227 if(nu->type == CU_BEZIER) { 05228 a= nu->pntsu; 05229 bezt= nu->bezt; 05230 while(a--) { 05231 if((bezt->hide==0) && (bezt->f2 & SELECT)) { 05232 if(lastsel==1) sel= 1; 05233 else sel= 0; 05234 05235 /* check if neighbours have been selected */ 05236 /* first and last are exceptions */ 05237 if(a==nu->pntsu-1) sel++; 05238 else { 05239 bezt--; 05240 if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++; 05241 bezt++; 05242 } 05243 05244 if(a==0) sel++; 05245 else { 05246 bezt++; 05247 if((bezt->hide==0) && (bezt->f2 & SELECT)) sel++; 05248 bezt--; 05249 } 05250 05251 if(sel!=2) { 05252 select_beztriple(bezt, DESELECT, 1, VISIBLE); 05253 lastsel= 1; 05254 } 05255 else lastsel= 0; 05256 } 05257 else lastsel= 0; 05258 05259 bezt++; 05260 } 05261 } 05262 else { 05263 a= nu->pntsu*nu->pntsv; 05264 bp= nu->bp; 05265 while(a--) { 05266 if((lastsel==0) && (bp->hide==0) && (bp->f1 & SELECT)) { 05267 if(lastsel!=0) sel= 1; 05268 else sel= 0; 05269 05270 /* first and last are exceptions */ 05271 if(a==nu->pntsu*nu->pntsv-1) sel++; 05272 else { 05273 bp--; 05274 if((bp->hide==0) && (bp->f1 & SELECT)) sel++; 05275 bp++; 05276 } 05277 05278 if(a==0) sel++; 05279 else { 05280 bp++; 05281 if((bp->hide==0) && (bp->f1 & SELECT)) sel++; 05282 bp--; 05283 } 05284 05285 if(sel!=2) { 05286 select_bpoint(bp, DESELECT, 1, VISIBLE); 05287 lastsel= 1; 05288 } 05289 else lastsel= 0; 05290 } 05291 else lastsel= 0; 05292 05293 bp++; 05294 } 05295 } 05296 } 05297 } 05298 05299 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05300 05301 return OPERATOR_FINISHED; 05302 } 05303 05304 void CURVE_OT_select_less(wmOperatorType *ot) 05305 { 05306 /* identifiers */ 05307 ot->name= "Select Less"; 05308 ot->idname= "CURVE_OT_select_less"; 05309 05310 /* api callbacks */ 05311 ot->exec= select_less_exec; 05312 ot->poll= ED_operator_editsurfcurve; 05313 05314 /* flags */ 05315 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05316 } 05317 05318 /********************** select random *********************/ 05319 05320 static void selectrandom_curve(ListBase *editnurb, float randfac) 05321 { 05322 Nurb *nu; 05323 BezTriple *bezt; 05324 BPoint *bp; 05325 int a; 05326 05327 BLI_srand( BLI_rand() ); /* random seed */ 05328 05329 for(nu= editnurb->first; nu; nu= nu->next) { 05330 if(nu->type == CU_BEZIER) { 05331 bezt= nu->bezt; 05332 a= nu->pntsu; 05333 while(a--) { 05334 if (BLI_frand() < randfac) 05335 select_beztriple(bezt, SELECT, 1, VISIBLE); 05336 bezt++; 05337 } 05338 } 05339 else { 05340 bp= nu->bp; 05341 a= nu->pntsu*nu->pntsv; 05342 05343 while(a--) { 05344 if (BLI_frand() < randfac) 05345 select_bpoint(bp, SELECT, 1, VISIBLE); 05346 bp++; 05347 } 05348 } 05349 } 05350 } 05351 05352 static int select_random_exec(bContext *C, wmOperator *op) 05353 { 05354 Object *obedit= CTX_data_edit_object(C); 05355 ListBase *editnurb= object_editcurve_get(obedit); 05356 05357 if(!RNA_boolean_get(op->ptr, "extend")) 05358 CU_deselect_all(obedit); 05359 05360 selectrandom_curve(editnurb, RNA_float_get(op->ptr, "percent")/100.0f); 05361 05362 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05363 05364 return OPERATOR_FINISHED; 05365 } 05366 05367 void CURVE_OT_select_random(wmOperatorType *ot) 05368 { 05369 /* identifiers */ 05370 ot->name= "Select Random"; 05371 ot->idname= "CURVE_OT_select_random"; 05372 05373 /* api callbacks */ 05374 ot->exec= select_random_exec; 05375 ot->poll= ED_operator_editsurfcurve; 05376 05377 /* flags */ 05378 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05379 05380 /* properties */ 05381 RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); 05382 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first"); 05383 } 05384 05385 /********************* every nth number of point *******************/ 05386 05387 static int point_on_nurb(Nurb *nu, void *point) 05388 { 05389 if (nu->bezt) { 05390 BezTriple *bezt= (BezTriple*)point; 05391 return bezt >= nu->bezt && bezt < nu->bezt + nu->pntsu; 05392 } else { 05393 BPoint *bp= (BPoint*)point; 05394 return bp >= nu->bp && bp < nu->bp + nu->pntsu * nu->pntsv; 05395 } 05396 } 05397 05398 static Nurb *get_lastsel_nurb(Curve *cu) 05399 { 05400 ListBase *nubase= curve_editnurbs(cu); 05401 Nurb *nu= nubase->first; 05402 05403 if(!cu->lastsel) 05404 return NULL; 05405 05406 while (nu) { 05407 if (point_on_nurb(nu, cu->lastsel)) 05408 return nu; 05409 05410 nu= nu->next; 05411 } 05412 05413 return NULL; 05414 } 05415 05416 static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth) 05417 { 05418 int a, start; 05419 05420 start= bezt - nu->bezt; 05421 a= nu->pntsu; 05422 bezt= nu->bezt + a - 1; 05423 05424 while (a--) { 05425 if (abs(start - a) % nth) { 05426 select_beztriple(bezt, DESELECT, 1, HIDDEN); 05427 } 05428 05429 bezt--; 05430 } 05431 } 05432 05433 static void select_nth_bp(Nurb *nu, BPoint *bp, int nth) 05434 { 05435 int a, startrow, startpnt; 05436 int dist, row, pnt; 05437 05438 startrow= (bp - nu->bp) / nu->pntsu; 05439 startpnt= (bp - nu->bp) % nu->pntsu; 05440 05441 a= nu->pntsu * nu->pntsv; 05442 bp= nu->bp + a - 1; 05443 row = nu->pntsv - 1; 05444 pnt = nu->pntsu - 1; 05445 05446 while (a--) { 05447 dist= abs(pnt - startpnt) + abs(row - startrow); 05448 if (dist % nth) { 05449 select_bpoint(bp, DESELECT, 1, HIDDEN); 05450 } 05451 05452 pnt--; 05453 if (pnt < 0) { 05454 pnt= nu->pntsu - 1; 05455 row--; 05456 } 05457 05458 bp--; 05459 } 05460 } 05461 05462 int CU_select_nth(Object *obedit, int nth) 05463 { 05464 Curve *cu= (Curve*)obedit->data; 05465 Nurb *nu; 05466 05467 nu= get_lastsel_nurb(cu); 05468 if (!nu) 05469 return 0; 05470 05471 if (nu->bezt) { 05472 select_nth_bezt(nu, cu->lastsel, nth); 05473 } else { 05474 select_nth_bp(nu, cu->lastsel, nth); 05475 } 05476 05477 return 1; 05478 } 05479 05480 static int select_nth_exec(bContext *C, wmOperator *op) 05481 { 05482 Object *obedit= CTX_data_edit_object(C); 05483 int nth= RNA_int_get(op->ptr, "nth"); 05484 05485 if (!CU_select_nth(obedit, nth)) { 05486 if (obedit->type == OB_SURF) { 05487 BKE_report(op->reports, RPT_ERROR, "Surface hasn't got active point"); 05488 } else { 05489 BKE_report(op->reports, RPT_ERROR, "Curve hasn't got active point"); 05490 } 05491 05492 return OPERATOR_CANCELLED; 05493 } 05494 05495 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05496 05497 return OPERATOR_FINISHED; 05498 } 05499 05500 void CURVE_OT_select_nth(wmOperatorType *ot) 05501 { 05502 /* identifiers */ 05503 ot->name= "Select Nth"; 05504 ot->description= ""; 05505 ot->idname= "CURVE_OT_select_nth"; 05506 05507 /* api callbacks */ 05508 ot->exec= select_nth_exec; 05509 ot->poll= ED_operator_editsurfcurve; 05510 05511 /* flags */ 05512 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05513 05514 RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX); 05515 } 05516 05517 /********************** add duplicate operator *********************/ 05518 05519 static int duplicate_exec(bContext *C, wmOperator *UNUSED(op)) 05520 { 05521 Object *obedit= CTX_data_edit_object(C); 05522 05523 adduplicateflagNurb(obedit, 1); 05524 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 05525 05526 return OPERATOR_FINISHED; 05527 } 05528 05529 void CURVE_OT_duplicate(wmOperatorType *ot) 05530 { 05531 /* identifiers */ 05532 ot->name= "Duplicate Curve"; 05533 ot->description = "Duplicate selected control points and segments between them"; 05534 ot->idname= "CURVE_OT_duplicate"; 05535 05536 /* api callbacks */ 05537 ot->exec= duplicate_exec; 05538 ot->poll= ED_operator_editsurfcurve; 05539 05540 /* flags */ 05541 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05542 } 05543 05544 /********************** delete operator *********************/ 05545 05546 static int delete_exec(bContext *C, wmOperator *op) 05547 { 05548 Object *obedit= CTX_data_edit_object(C); 05549 Curve *cu= obedit->data; 05550 EditNurb *editnurb= cu->editnurb; 05551 ListBase *nubase= &editnurb->nurbs; 05552 Nurb *nu, *nu1; 05553 BezTriple *bezt, *bezt1, *bezt2; 05554 BPoint *bp, *bp1, *bp2; 05555 int a, cut= 0, type= RNA_enum_get(op->ptr, "type"); 05556 int nuindex= 0; 05557 05558 if(obedit->type==OB_SURF) { 05559 if(type==0) { 05560 deleteflagNurb(C, op, 1); 05561 } else { 05562 keyIndex_delNurbList(editnurb, nubase); 05563 freeNurblist(nubase); 05564 05565 if(ED_curve_updateAnimPaths(obedit)) 05566 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 05567 } 05568 05569 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 05570 DAG_id_tag_update(obedit->data, 0); 05571 05572 return OPERATOR_FINISHED; 05573 } 05574 05575 if(type==0) { 05576 /* first loop, can we remove entire pieces? */ 05577 Nurb *next; 05578 nu= nubase->first; 05579 while(nu) { 05580 next= nu->next; 05581 if(nu->type == CU_BEZIER) { 05582 bezt= nu->bezt; 05583 a= nu->pntsu; 05584 if(a) { 05585 while(a) { 05586 if( BEZSELECTED_HIDDENHANDLES(cu, bezt) ); 05587 else break; 05588 a--; 05589 bezt++; 05590 } 05591 if(a==0) { 05592 if(cu->actnu == nuindex) 05593 cu->actnu= -1; 05594 05595 BLI_remlink(nubase, nu); 05596 keyIndex_delNurb(editnurb, nu); 05597 freeNurb(nu); nu= NULL; 05598 } 05599 } 05600 } 05601 else { 05602 bp= nu->bp; 05603 a= nu->pntsu*nu->pntsv; 05604 if(a) { 05605 while(a) { 05606 if(bp->f1 & SELECT); 05607 else break; 05608 a--; 05609 bp++; 05610 } 05611 if(a==0) { 05612 if(cu->actnu == nuindex) 05613 cu->actnu= -1; 05614 05615 BLI_remlink(nubase, nu); 05616 keyIndex_delNurb(editnurb, nu); 05617 freeNurb(nu); nu= NULL; 05618 } 05619 } 05620 } 05621 05622 /* Never allow the order to exceed the number of points 05623 - note, this is ok but changes unselected nurbs, disable for now */ 05624 /* 05625 if ((nu!= NULL) && (nu->type == CU_NURBS)) { 05626 clamp_nurb_order_u(nu); 05627 } 05628 */ 05629 nu= next; 05630 nuindex++; 05631 } 05632 /* 2nd loop, delete small pieces: just for curves */ 05633 nu= nubase->first; 05634 while(nu) { 05635 next= nu->next; 05636 type= 0; 05637 if(nu->type == CU_BEZIER) { 05638 int delta= 0; 05639 bezt= nu->bezt; 05640 for(a=0;a<nu->pntsu;a++) { 05641 if( BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { 05642 memmove(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple)); 05643 keyIndex_delBezt(editnurb, bezt + delta); 05644 keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu-a-1); 05645 nu->pntsu--; 05646 a--; 05647 type= 1; 05648 delta++; 05649 } 05650 else bezt++; 05651 } 05652 if(type) { 05653 bezt1 = 05654 (BezTriple*)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb"); 05655 memcpy(bezt1, nu->bezt, (nu->pntsu)*sizeof(BezTriple) ); 05656 keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu); 05657 MEM_freeN(nu->bezt); 05658 nu->bezt= bezt1; 05659 calchandlesNurb(nu); 05660 } 05661 } 05662 else if(nu->pntsv==1) { 05663 int delta= 0; 05664 bp= nu->bp; 05665 05666 for(a=0;a<nu->pntsu;a++) { 05667 if( bp->f1 & SELECT ) { 05668 memmove(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint)); 05669 keyIndex_delBP(editnurb, bp + delta); 05670 keyIndex_updateBP(editnurb, bp+1, bp, nu->pntsu-a-1); 05671 nu->pntsu--; 05672 a--; 05673 type= 1; 05674 delta++; 05675 } 05676 else { 05677 bp++; 05678 } 05679 } 05680 if(type) { 05681 bp1 = (BPoint*)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2"); 05682 memcpy(bp1, nu->bp, (nu->pntsu)*sizeof(BPoint) ); 05683 keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu); 05684 MEM_freeN(nu->bp); 05685 nu->bp= bp1; 05686 05687 /* Never allow the order to exceed the number of points\ 05688 - note, this is ok but changes unselected nurbs, disable for now */ 05689 /* 05690 if (nu->type == CU_NURBS) { 05691 clamp_nurb_order_u(nu); 05692 }*/ 05693 } 05694 clamp_nurb_order_u(nu); 05695 nurbs_knot_calc_u(nu); 05696 } 05697 nu= next; 05698 } 05699 } 05700 else if(type==1) { /* erase segment */ 05701 /* find the 2 selected points */ 05702 bezt1= bezt2= NULL; 05703 bp1= bp2= NULL; 05704 nu1= NULL; 05705 nuindex= 0; 05706 for(nu= nubase->first; nu; nu= nu->next) { 05707 if(nu->type == CU_BEZIER) { 05708 bezt= nu->bezt; 05709 for(a=0; a<nu->pntsu-1; a++) { 05710 if( BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { 05711 bezt1= bezt; 05712 bezt2= bezt+1; 05713 if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) ; 05714 else { /* maybe do not make cyclic */ 05715 if(a==0 && (nu->flagu & CU_NURB_CYCLIC) ) { 05716 bezt2= bezt+(nu->pntsu-1); 05717 if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) { 05718 nu->flagu &= ~CU_NURB_CYCLIC; 05719 calchandlesNurb(nu); 05720 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 05721 DAG_id_tag_update(obedit->data, 0); 05722 } 05723 } 05724 05725 return OPERATOR_FINISHED; 05726 } 05727 cut= a; 05728 nu1= nu; 05729 break; 05730 } 05731 bezt++; 05732 } 05733 } 05734 else if(nu->pntsv==1) { 05735 bp= nu->bp; 05736 for(a=0; a<nu->pntsu-1; a++) { 05737 if( bp->f1 & SELECT ) { 05738 bp1= bp; 05739 bp2= bp+1; 05740 if( bp2->f1 & 1 ) ; 05741 else { /* maybe do not make cyclic */ 05742 if(a==0 && (nu->flagu & CU_NURB_CYCLIC) ) { 05743 bp2= bp+(nu->pntsu-1); 05744 if( bp2->f1 & SELECT ) { 05745 nu->flagu &= ~CU_NURB_CYCLIC; 05746 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 05747 DAG_id_tag_update(obedit->data, 0); 05748 } 05749 } 05750 05751 return OPERATOR_FINISHED; 05752 } 05753 cut= a; 05754 nu1= nu; 05755 break; 05756 } 05757 bp++; 05758 } 05759 } 05760 if(nu1) break; 05761 nuindex++; 05762 } 05763 if(nu1) { 05764 if(bezt1) { 05765 if(nu1->pntsu==2) { /* remove completely */ 05766 if(cu->actnu == nuindex) 05767 cu->actnu= -1; 05768 05769 BLI_remlink(nubase, nu); 05770 freeNurb(nu); nu = NULL; 05771 } 05772 else if(nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */ 05773 bezt = 05774 (BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb1"); 05775 ED_curve_beztcpy(editnurb, bezt, nu1->bezt, cut+1); 05776 a= nu1->pntsu-cut-1; 05777 ED_curve_beztcpy(editnurb, nu1->bezt, bezt2, a); 05778 ED_curve_beztcpy(editnurb, nu1->bezt+a, bezt, cut+1); 05779 05780 nu1->flagu &= ~CU_NURB_CYCLIC; 05781 MEM_freeN(bezt); 05782 calchandlesNurb(nu); 05783 } 05784 else { /* add new curve */ 05785 05786 /* seems to be an error here... but where? (a can become zero) */ 05787 05788 nu = 05789 (Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb2"); 05790 memcpy(nu, nu1, sizeof(Nurb)); 05791 BLI_addtail(nubase, nu); 05792 nu->bezt = 05793 (BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb3"); 05794 ED_curve_beztcpy(editnurb, nu->bezt, nu1->bezt, cut+1); 05795 a= nu1->pntsu-cut-1; 05796 05797 bezt = 05798 (BezTriple*)MEM_mallocN(a * sizeof(BezTriple), "delNurb4"); 05799 ED_curve_beztcpy(editnurb, bezt, nu1->bezt+cut+1, a); 05800 MEM_freeN(nu1->bezt); 05801 nu1->bezt= bezt; 05802 nu1->pntsu= a; 05803 nu->pntsu= cut+1; 05804 05805 05806 calchandlesNurb(nu); 05807 calchandlesNurb(nu1); 05808 } 05809 } 05810 else if(bp1) { 05811 if(nu1->pntsu==2) { /* remove completely */ 05812 if(cu->actnu == nuindex) 05813 cu->actnu= -1; 05814 05815 BLI_remlink(nubase, nu); 05816 freeNurb(nu); nu= NULL; 05817 } 05818 else if(nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */ 05819 bp = 05820 (BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb5"); 05821 ED_curve_bpcpy(editnurb, bp, nu1->bp, cut+1); 05822 a= nu1->pntsu-cut-1; 05823 ED_curve_bpcpy(editnurb, nu1->bp, bp2, a); 05824 ED_curve_bpcpy(editnurb, nu1->bp+a, bp, cut+1); 05825 05826 nu1->flagu &= ~CU_NURB_CYCLIC; 05827 MEM_freeN(bp); 05828 } 05829 else { /* add new curve */ 05830 nu = (Nurb*)MEM_mallocN(sizeof(Nurb), "delNurb6"); 05831 memcpy(nu, nu1, sizeof(Nurb)); 05832 BLI_addtail(nubase, nu); 05833 nu->bp = 05834 (BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb7"); 05835 ED_curve_bpcpy(editnurb, nu->bp, nu1->bp, cut+1); 05836 a= nu1->pntsu-cut-1; 05837 bp = 05838 (BPoint*)MEM_mallocN(a * sizeof(BPoint), "delNurb8"); 05839 ED_curve_bpcpy(editnurb, bp, nu1->bp+cut+1, a); 05840 MEM_freeN(nu1->bp); 05841 nu1->bp= bp; 05842 nu1->pntsu= a; 05843 nu1->knotsu= NULL; 05844 nu->pntsu= cut+1; 05845 05846 clamp_nurb_order_u(nu); 05847 nurbs_knot_calc_u(nu); 05848 05849 clamp_nurb_order_u(nu1); 05850 nurbs_knot_calc_u(nu1); 05851 } 05852 } 05853 } 05854 } 05855 else if(type==2) { 05856 cu->actnu= -1; 05857 keyIndex_delNurbList(editnurb, nubase); 05858 freeNurblist(nubase); 05859 } 05860 05861 if(ED_curve_updateAnimPaths(obedit)) 05862 WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obedit); 05863 05864 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 05865 DAG_id_tag_update(obedit->data, 0); 05866 05867 return OPERATOR_FINISHED; 05868 } 05869 05870 static int delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 05871 { 05872 Object *obedit= CTX_data_edit_object(C); 05873 uiPopupMenu *pup; 05874 uiLayout *layout; 05875 05876 if(obedit->type==OB_SURF) { 05877 pup= uiPupMenuBegin(C, "Delete", ICON_NONE); 05878 layout= uiPupMenuLayout(pup); 05879 uiItemEnumO(layout, op->type->idname, NULL, 0, "type", 0); 05880 uiItemEnumO(layout, op->type->idname, NULL, 0, "type", 2); 05881 uiPupMenuEnd(C, pup); 05882 } 05883 else { 05884 pup= uiPupMenuBegin(C, "Delete", ICON_NONE); 05885 layout= uiPupMenuLayout(pup); 05886 uiItemsEnumO(layout, op->type->idname, "type"); 05887 uiPupMenuEnd(C, pup); 05888 } 05889 05890 return OPERATOR_CANCELLED; 05891 } 05892 05893 void CURVE_OT_delete(wmOperatorType *ot) 05894 { 05895 static EnumPropertyItem type_items[] = { 05896 {0, "SELECTED", 0, "Select", ""}, 05897 {1, "SEGMENT", 0, "Segment", ""}, 05898 {2, "ALL", 0, "All", ""}, 05899 {0, NULL, 0, NULL, NULL}}; 05900 05901 /* identifiers */ 05902 ot->name= "Delete"; 05903 ot->description = "Delete selected control points or segments"; 05904 ot->idname= "CURVE_OT_delete"; 05905 05906 /* api callbacks */ 05907 ot->exec= delete_exec; 05908 ot->invoke= delete_invoke; 05909 ot->poll= ED_operator_editsurfcurve; 05910 05911 /* flags */ 05912 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05913 05914 /* properties */ 05915 RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Which elements to delete"); 05916 } 05917 05918 /********************** shade smooth/flat operator *********************/ 05919 05920 static int shade_smooth_exec(bContext *C, wmOperator *op) 05921 { 05922 Object *obedit= CTX_data_edit_object(C); 05923 ListBase *editnurb= object_editcurve_get(obedit); 05924 Nurb *nu; 05925 int clear= (strcmp(op->idname, "CURVE_OT_shade_flat") == 0); 05926 05927 if(obedit->type != OB_CURVE) 05928 return OPERATOR_CANCELLED; 05929 05930 for(nu= editnurb->first; nu; nu= nu->next) { 05931 if(isNurbsel(nu)) { 05932 if(!clear) nu->flag |= CU_SMOOTH; 05933 else nu->flag &= ~CU_SMOOTH; 05934 } 05935 } 05936 05937 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 05938 DAG_id_tag_update(obedit->data, 0); 05939 05940 return OPERATOR_FINISHED; 05941 } 05942 05943 void CURVE_OT_shade_smooth(wmOperatorType *ot) 05944 { 05945 /* identifiers */ 05946 ot->name= "Shade Smooth"; 05947 ot->idname= "CURVE_OT_shade_smooth"; 05948 05949 /* api callbacks */ 05950 ot->exec= shade_smooth_exec; 05951 ot->poll= ED_operator_editsurfcurve; 05952 05953 /* flags */ 05954 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05955 } 05956 05957 void CURVE_OT_shade_flat(wmOperatorType *ot) 05958 { 05959 /* identifiers */ 05960 ot->name= "Shade Flat"; 05961 ot->idname= "CURVE_OT_shade_flat"; 05962 05963 /* api callbacks */ 05964 ot->exec= shade_smooth_exec; 05965 ot->poll= ED_operator_editsurfcurve; 05966 05967 /* flags */ 05968 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 05969 } 05970 05971 /************** join operator, to be used externally? ****************/ 05972 05973 int join_curve_exec(bContext *C, wmOperator *UNUSED(op)) 05974 { 05975 Main *bmain= CTX_data_main(C); 05976 Scene *scene= CTX_data_scene(C); 05977 Object *ob= CTX_data_active_object(C); 05978 Curve *cu; 05979 Nurb *nu, *newnu; 05980 BezTriple *bezt; 05981 BPoint *bp; 05982 ListBase tempbase; 05983 float imat[4][4], cmat[4][4]; 05984 int a; 05985 05986 tempbase.first= tempbase.last= NULL; 05987 05988 /* trasnform all selected curves inverse in obact */ 05989 invert_m4_m4(imat, ob->obmat); 05990 05991 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { 05992 if(base->object->type==ob->type) { 05993 if(base->object != ob) { 05994 05995 cu= base->object->data; 05996 05997 if(cu->nurb.first) { 05998 /* watch it: switch order here really goes wrong */ 05999 mult_m4_m4m4(cmat, imat, base->object->obmat); 06000 06001 nu= cu->nurb.first; 06002 while(nu) { 06003 newnu= duplicateNurb(nu); 06004 if(ob->totcol) { /* TODO, merge material lists */ 06005 CLAMP(newnu->mat_nr, 0, ob->totcol-1); 06006 } else newnu->mat_nr= 0; 06007 BLI_addtail(&tempbase, newnu); 06008 06009 if( (bezt= newnu->bezt) ) { 06010 a= newnu->pntsu; 06011 while(a--) { 06012 mul_m4_v3(cmat, bezt->vec[0]); 06013 mul_m4_v3(cmat, bezt->vec[1]); 06014 mul_m4_v3(cmat, bezt->vec[2]); 06015 bezt++; 06016 } 06017 calchandlesNurb(newnu); 06018 } 06019 if( (bp= newnu->bp) ) { 06020 a= newnu->pntsu*nu->pntsv; 06021 while(a--) { 06022 mul_m4_v3(cmat, bp->vec); 06023 bp++; 06024 } 06025 } 06026 nu= nu->next; 06027 } 06028 } 06029 06030 ED_base_object_free_and_unlink(bmain, scene, base); 06031 } 06032 } 06033 } 06034 CTX_DATA_END; 06035 06036 cu= ob->data; 06037 BLI_movelisttolist(&cu->nurb, &tempbase); 06038 06039 DAG_scene_sort(bmain, scene); // because we removed object(s), call before editmode! 06040 06041 ED_object_enter_editmode(C, EM_WAITCURSOR); 06042 ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO); 06043 06044 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); 06045 06046 return OPERATOR_FINISHED; 06047 } 06048 06049 /************ add primitive, used by object/ module ****************/ 06050 06051 static const char *get_curve_defname(int type) 06052 { 06053 int stype= type & CU_PRIMITIVE; 06054 06055 if((type & CU_TYPE)==CU_BEZIER) { 06056 switch (stype) { 06057 case CU_PRIM_CURVE: return "BezierCurve"; 06058 case CU_PRIM_CIRCLE: return "BezierCircle"; 06059 case CU_PRIM_PATH: return "CurvePath"; 06060 default: 06061 return "Curve"; 06062 } 06063 } 06064 else { 06065 switch (stype) { 06066 case CU_PRIM_CURVE: return "NurbsCurve"; 06067 case CU_PRIM_CIRCLE: return "NurbsCircle"; 06068 case CU_PRIM_PATH: return "NurbsPath"; 06069 default: 06070 return "Curve"; 06071 } 06072 } 06073 } 06074 06075 static const char *get_surf_defname(int type) 06076 { 06077 int stype= type & CU_PRIMITIVE; 06078 06079 switch (stype) { 06080 case CU_PRIM_CURVE: return "SurfCurve"; 06081 case CU_PRIM_CIRCLE: return "SurfCircle"; 06082 case CU_PRIM_PATCH: return "SurfPatch"; 06083 case CU_PRIM_SPHERE: return "SurfSphere"; 06084 case CU_PRIM_DONUT: return "SurfTorus"; 06085 default: 06086 return "Surface"; 06087 } 06088 } 06089 06090 06091 Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) 06092 { 06093 static int xzproj= 0; /* this function calls itself... */ 06094 Object *obedit= CTX_data_edit_object(C); 06095 ListBase *editnurb= object_editcurve_get(obedit); 06096 View3D *v3d= CTX_wm_view3d(C); 06097 RegionView3D *rv3d= ED_view3d_context_rv3d(C); 06098 Nurb *nu = NULL; 06099 BezTriple *bezt; 06100 BPoint *bp; 06101 Curve *cu= (Curve*)obedit->data; 06102 float vec[3], zvec[3]= {0.0f, 0.0f, 1.0f}; 06103 float umat[4][4]= MAT4_UNITY, viewmat[4][4]= MAT4_UNITY; 06104 float fac; 06105 int a, b; 06106 const float grid= v3d ? v3d->grid : 1.0f; 06107 const int cutype= (type & CU_TYPE); // poly, bezier, nurbs, etc 06108 const int stype= (type & CU_PRIMITIVE); 06109 const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */ 06110 06111 if(rv3d) { 06112 copy_m4_m4(viewmat, rv3d->viewmat); 06113 copy_v3_v3(zvec, rv3d->viewinv[2]); 06114 } 06115 06116 setflagsNurb(editnurb, 0); 06117 06118 /* these types call this function to return a Nurb */ 06119 if (stype!=CU_PRIM_TUBE && stype!=CU_PRIM_DONUT) { 06120 nu = (Nurb*)MEM_callocN(sizeof(Nurb), "addNurbprim"); 06121 nu->type= cutype; 06122 nu->resolu= cu->resolu; 06123 nu->resolv= cu->resolv; 06124 } 06125 06126 switch(stype) { 06127 case CU_PRIM_CURVE: /* curve */ 06128 nu->resolu= cu->resolu; 06129 if(cutype==CU_BEZIER) { 06130 if (!force_3d) nu->flag |= CU_2D; 06131 nu->pntsu= 2; 06132 nu->bezt = 06133 (BezTriple*)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1"); 06134 bezt= nu->bezt; 06135 bezt->h1= bezt->h2= HD_ALIGN; 06136 bezt->f1= bezt->f2= bezt->f3= SELECT; 06137 bezt->radius = 1.0; 06138 06139 bezt->vec[1][0]+= -grid; 06140 bezt->vec[0][0]+= -1.5f*grid; 06141 bezt->vec[0][1]+= -0.5f*grid; 06142 bezt->vec[2][0]+= -0.5f*grid; 06143 bezt->vec[2][1]+= 0.5f*grid; 06144 for(a=0;a<3;a++) mul_m4_v3(mat, bezt->vec[a]); 06145 06146 bezt++; 06147 bezt->h1= bezt->h2= HD_ALIGN; 06148 bezt->f1= bezt->f2= bezt->f3= SELECT; 06149 bezt->radius = bezt->weight = 1.0; 06150 06151 bezt->vec[0][0] = 0; 06152 bezt->vec[0][1] = 0; 06153 bezt->vec[1][0] = grid; 06154 bezt->vec[1][1] = 0; 06155 bezt->vec[2][0] = grid*2; 06156 bezt->vec[2][1] = 0; 06157 for(a=0;a<3;a++) mul_m4_v3(mat, bezt->vec[a]); 06158 06159 calchandlesNurb(nu); 06160 } 06161 else { 06162 06163 nu->pntsu= 4; 06164 nu->pntsv= 1; 06165 nu->orderu= 4; 06166 nu->bp= callocstructN(BPoint, 4, "addNurbprim3"); 06167 06168 bp= nu->bp; 06169 for(a=0;a<4;a++, bp++) { 06170 bp->vec[3]= 1.0; 06171 bp->f1= SELECT; 06172 bp->radius = bp->weight = 1.0; 06173 } 06174 06175 bp= nu->bp; 06176 bp->vec[0]+= -1.5f*grid; 06177 bp++; 06178 bp->vec[0]+= -grid; 06179 bp->vec[1]+= grid; 06180 bp++; 06181 bp->vec[0]+= grid; 06182 bp->vec[1]+= grid; 06183 bp++; 06184 bp->vec[0]+= 1.5f*grid; 06185 06186 bp= nu->bp; 06187 for(a=0;a<4;a++, bp++) mul_m4_v3(mat,bp->vec); 06188 06189 if(cutype==CU_NURBS) { 06190 nu->knotsu= NULL; /* nurbs_knot_calc_u allocates */ 06191 nurbs_knot_calc_u(nu); 06192 } 06193 06194 } 06195 break; 06196 case CU_PRIM_PATH: /* 5 point path */ 06197 nu->pntsu= 5; 06198 nu->pntsv= 1; 06199 nu->orderu= 5; 06200 nu->flagu= CU_NURB_ENDPOINT; /* endpoint */ 06201 nu->resolu= cu->resolu; 06202 nu->bp= callocstructN(BPoint, 5, "addNurbprim3"); 06203 06204 bp= nu->bp; 06205 for(a=0;a<5;a++, bp++) { 06206 bp->vec[3]= 1.0; 06207 bp->f1= SELECT; 06208 bp->radius = bp->weight = 1.0; 06209 } 06210 06211 bp= nu->bp; 06212 bp->vec[0]+= -2.0f*grid; 06213 bp++; 06214 bp->vec[0]+= -grid; 06215 bp++; bp++; 06216 bp->vec[0]+= grid; 06217 bp++; 06218 bp->vec[0]+= 2.0f*grid; 06219 06220 bp= nu->bp; 06221 for(a=0;a<5;a++, bp++) mul_m4_v3(mat,bp->vec); 06222 06223 if(cutype==CU_NURBS) { 06224 nu->knotsu= NULL; /* nurbs_knot_calc_u allocates */ 06225 nurbs_knot_calc_u(nu); 06226 } 06227 06228 break; 06229 case CU_PRIM_CIRCLE: /* circle */ 06230 nu->resolu= cu->resolu; 06231 06232 if(cutype==CU_BEZIER) { 06233 if (!force_3d) nu->flag |= CU_2D; 06234 nu->pntsu= 4; 06235 nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1"); 06236 nu->flagu= CU_NURB_CYCLIC; 06237 bezt= nu->bezt; 06238 06239 bezt->h1= bezt->h2= HD_AUTO; 06240 bezt->f1= bezt->f2= bezt->f3= SELECT; 06241 bezt->vec[1][0]+= -grid; 06242 for(a=0;a<3;a++) mul_m4_v3(mat,bezt->vec[a]); 06243 bezt->radius = bezt->weight = 1.0; 06244 06245 bezt++; 06246 bezt->h1= bezt->h2= HD_AUTO; 06247 bezt->f1= bezt->f2= bezt->f3= SELECT; 06248 bezt->vec[1][1]+= grid; 06249 for(a=0;a<3;a++) mul_m4_v3(mat,bezt->vec[a]); 06250 bezt->radius = bezt->weight = 1.0; 06251 06252 bezt++; 06253 bezt->h1= bezt->h2= HD_AUTO; 06254 bezt->f1= bezt->f2= bezt->f3= SELECT; 06255 bezt->vec[1][0]+= grid; 06256 for(a=0;a<3;a++) mul_m4_v3(mat,bezt->vec[a]); 06257 bezt->radius = bezt->weight = 1.0; 06258 06259 bezt++; 06260 bezt->h1= bezt->h2= HD_AUTO; 06261 bezt->f1= bezt->f2= bezt->f3= SELECT; 06262 bezt->vec[1][1]+= -grid; 06263 for(a=0;a<3;a++) mul_m4_v3(mat,bezt->vec[a]); 06264 bezt->radius = bezt->weight = 1.0; 06265 06266 calchandlesNurb(nu); 06267 } 06268 else if( cutype==CU_NURBS ) { /* nurb */ 06269 nu->pntsu= 8; 06270 nu->pntsv= 1; 06271 nu->orderu= 4; 06272 nu->bp= callocstructN(BPoint, 8, "addNurbprim6"); 06273 nu->flagu= CU_NURB_CYCLIC; 06274 bp= nu->bp; 06275 06276 for(a=0; a<8; a++) { 06277 bp->f1= SELECT; 06278 if(xzproj==0) { 06279 bp->vec[0]+= nurbcircle[a][0]*grid; 06280 bp->vec[1]+= nurbcircle[a][1]*grid; 06281 } 06282 else { 06283 bp->vec[0]+= 0.25f*nurbcircle[a][0]*grid-0.75f*grid; 06284 bp->vec[2]+= 0.25f*nurbcircle[a][1]*grid; 06285 } 06286 if(a & 1) bp->vec[3]= 0.25*M_SQRT2; 06287 else bp->vec[3]= 1.0; 06288 mul_m4_v3(mat,bp->vec); 06289 bp->radius = bp->weight = 1.0; 06290 06291 bp++; 06292 } 06293 06294 nurbs_knot_calc_u(nu); 06295 } 06296 break; 06297 case CU_PRIM_PATCH: /* 4x4 patch */ 06298 if( cutype==CU_NURBS ) { /* nurb */ 06299 06300 nu->pntsu= 4; 06301 nu->pntsv= 4; 06302 nu->orderu= 4; 06303 nu->orderv= 4; 06304 nu->flag= CU_SMOOTH; 06305 nu->bp= callocstructN(BPoint, 4*4, "addNurbprim6"); 06306 nu->flagu= 0; 06307 nu->flagv= 0; 06308 bp= nu->bp; 06309 06310 for(a=0; a<4; a++) { 06311 for(b=0; b<4; b++) { 06312 bp->f1= SELECT; 06313 fac= (float)a -1.5f; 06314 bp->vec[0]+= fac*grid; 06315 fac= (float)b -1.5f; 06316 bp->vec[1]+= fac*grid; 06317 if(a==1 || a==2) if(b==1 || b==2) { 06318 bp->vec[2]+= grid; 06319 } 06320 mul_m4_v3(mat,bp->vec); 06321 bp->vec[3]= 1.0; 06322 bp++; 06323 } 06324 } 06325 06326 nurbs_knot_calc_u(nu); 06327 nurbs_knot_calc_v(nu); 06328 } 06329 break; 06330 case CU_PRIM_TUBE: /* Cylinder */ 06331 if( cutype==CU_NURBS ) { 06332 nu= add_nurbs_primitive(C, mat, CU_NURBS|CU_PRIM_CIRCLE, 0); /* circle */ 06333 nu->resolu= cu->resolu; 06334 nu->flag= CU_SMOOTH; 06335 BLI_addtail(editnurb, nu); /* temporal for extrude and translate */ 06336 vec[0]=vec[1]= 0.0; 06337 vec[2]= -grid; 06338 06339 if(newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { 06340 /* pass */ 06341 } 06342 else { 06343 mul_mat3_m4_v3(mat, vec); 06344 } 06345 06346 translateflagNurb(editnurb, 1, vec); 06347 extrudeflagNurb(cu->editnurb, 1); 06348 vec[0]= -2*vec[0]; 06349 vec[1]= -2*vec[1]; 06350 vec[2]= -2*vec[2]; 06351 translateflagNurb(editnurb, 1, vec); 06352 06353 BLI_remlink(editnurb, nu); 06354 06355 a= nu->pntsu*nu->pntsv; 06356 bp= nu->bp; 06357 while(a-- >0) { 06358 bp->f1 |= SELECT; 06359 bp++; 06360 } 06361 } 06362 break; 06363 case CU_PRIM_SPHERE: /* sphere */ 06364 if( cutype==CU_NURBS ) { 06365 float tmp_cent[3] = {0.f, 0.f, 0.f}; 06366 float tmp_vec[3] = {0.f, 0.f, 1.f}; 06367 06368 nu->pntsu= 5; 06369 nu->pntsv= 1; 06370 nu->orderu= 3; 06371 nu->resolu= cu->resolu; 06372 nu->resolv= cu->resolv; 06373 nu->flag= CU_SMOOTH; 06374 nu->bp= callocstructN(BPoint, 5, "addNurbprim6"); 06375 nu->flagu= 0; 06376 bp= nu->bp; 06377 06378 for(a=0; a<5; a++) { 06379 bp->f1= SELECT; 06380 bp->vec[0]+= nurbcircle[a][0]*grid; 06381 bp->vec[2]+= nurbcircle[a][1]*grid; 06382 if(a & 1) bp->vec[3]= 0.5*M_SQRT2; 06383 else bp->vec[3]= 1.0; 06384 mul_m4_v3(mat,bp->vec); 06385 bp++; 06386 } 06387 nu->flagu= CU_NURB_BEZIER; 06388 nurbs_knot_calc_u(nu); 06389 06390 BLI_addtail(editnurb, nu); /* temporal for spin */ 06391 06392 if(newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) spin_nurb(umat, obedit, tmp_vec, tmp_cent); 06393 else if ((U.flag & USER_ADD_VIEWALIGNED)) spin_nurb(viewmat, obedit, zvec, mat[3]); 06394 else spin_nurb(umat, obedit, tmp_vec, mat[3]); 06395 06396 nurbs_knot_calc_v(nu); 06397 06398 a= nu->pntsu*nu->pntsv; 06399 bp= nu->bp; 06400 while(a-- >0) { 06401 bp->f1 |= SELECT; 06402 bp++; 06403 } 06404 BLI_remlink(editnurb, nu); 06405 } 06406 break; 06407 case CU_PRIM_DONUT: /* torus */ 06408 if( cutype==CU_NURBS ) { 06409 float tmp_cent[3] = {0.f, 0.f, 0.f}; 06410 float tmp_vec[3] = {0.f, 0.f, 1.f}; 06411 06412 xzproj= 1; 06413 nu= add_nurbs_primitive(C, mat, CU_NURBS|CU_PRIM_CIRCLE, 0); /* circle */ 06414 xzproj= 0; 06415 nu->resolu= cu->resolu; 06416 nu->resolv= cu->resolv; 06417 nu->flag= CU_SMOOTH; 06418 BLI_addtail(editnurb, nu); /* temporal for spin */ 06419 06420 /* same as above */ 06421 if(newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) spin_nurb(umat, obedit, tmp_vec, tmp_cent); 06422 else if ((U.flag & USER_ADD_VIEWALIGNED)) spin_nurb(viewmat, obedit, zvec, mat[3]); 06423 else spin_nurb(umat, obedit, tmp_vec, mat[3]); 06424 06425 06426 BLI_remlink(editnurb, nu); 06427 06428 a= nu->pntsu*nu->pntsv; 06429 bp= nu->bp; 06430 while(a-- >0) { 06431 bp->f1 |= SELECT; 06432 bp++; 06433 } 06434 06435 } 06436 break; 06437 06438 default: /* should never happen */ 06439 BLI_assert(!"invalid nurbs type"); 06440 return NULL; 06441 } 06442 06443 BLI_assert(nu != NULL); 06444 06445 if(nu) { /* should always be set */ 06446 nu->flag |= CU_SMOOTH; 06447 06448 test2DNurb(nu); 06449 } 06450 06451 return nu; 06452 } 06453 06454 static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) 06455 { 06456 Object *obedit= CTX_data_edit_object(C); 06457 ListBase *editnurb; 06458 Nurb *nu; 06459 int newob= 0; 06460 int enter_editmode; 06461 unsigned int layer; 06462 float loc[3], rot[3]; 06463 float mat[4][4]; 06464 06465 if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer)) 06466 return OPERATOR_CANCELLED; 06467 06468 if (!isSurf) { /* adding curve */ 06469 if(obedit==NULL || obedit->type!=OB_CURVE) { 06470 Curve *cu; 06471 06472 obedit= ED_object_add_type(C, OB_CURVE, loc, rot, TRUE, layer); 06473 newob = 1; 06474 06475 cu= (Curve*)obedit->data; 06476 cu->flag |= CU_DEFORM_FILL; 06477 06478 if(type & CU_PRIM_PATH) 06479 cu->flag |= CU_PATH|CU_3D; 06480 } 06481 else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 06482 } 06483 else { /* adding surface */ 06484 if(obedit==NULL || obedit->type!=OB_SURF) { 06485 obedit= ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer); 06486 newob = 1; 06487 } 06488 else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 06489 } 06490 06491 /* rename here, the undo stack checks name for valid undo pushes */ 06492 if(newob) { 06493 06494 if(obedit->type==OB_CURVE) { 06495 rename_id((ID *)obedit, get_curve_defname(type)); 06496 rename_id((ID *)obedit->data, get_curve_defname(type)); 06497 } 06498 else { 06499 rename_id((ID *)obedit, get_surf_defname(type)); 06500 rename_id((ID *)obedit->data, get_surf_defname(type)); 06501 } 06502 } 06503 06504 /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */ 06505 if(newob && enter_editmode) 06506 ED_undo_push(C, "Enter Editmode"); 06507 06508 ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); 06509 06510 nu= add_nurbs_primitive(C, mat, type, newob); 06511 editnurb= object_editcurve_get(obedit); 06512 BLI_addtail(editnurb, nu); 06513 06514 /* userdef */ 06515 if (newob && !enter_editmode) { 06516 ED_object_exit_editmode(C, EM_FREEDATA); 06517 } 06518 06519 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); 06520 06521 return OPERATOR_FINISHED; 06522 } 06523 06524 static int curve_prim_add(bContext *C, wmOperator *op, int type) 06525 { 06526 return curvesurf_prim_add(C, op, type, 0); 06527 } 06528 06529 static int surf_prim_add(bContext *C, wmOperator *op, int type) 06530 { 06531 return curvesurf_prim_add(C, op, type, 1); 06532 } 06533 06534 /* ******************** Curves ******************* */ 06535 06536 static int add_primitive_bezier_exec(bContext *C, wmOperator *op) 06537 { 06538 return curve_prim_add(C, op, CU_BEZIER|CU_PRIM_CURVE); 06539 } 06540 06541 void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot) 06542 { 06543 /* identifiers */ 06544 ot->name= "Add Bezier"; 06545 ot->description= "Construct a Bezier Curve"; 06546 ot->idname= "CURVE_OT_primitive_bezier_curve_add"; 06547 06548 /* api callbacks */ 06549 ot->invoke= ED_object_add_generic_invoke; 06550 ot->exec= add_primitive_bezier_exec; 06551 ot->poll= ED_operator_scene_editable; 06552 06553 /* flags */ 06554 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06555 06556 ED_object_add_generic_props(ot, TRUE); 06557 } 06558 06559 static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op) 06560 { 06561 return curve_prim_add(C, op, CU_BEZIER|CU_PRIM_CIRCLE); 06562 } 06563 06564 void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot) 06565 { 06566 /* identifiers */ 06567 ot->name= "Add Bezier Circle"; 06568 ot->description= "Construct a Bezier Circle"; 06569 ot->idname= "CURVE_OT_primitive_bezier_circle_add"; 06570 06571 /* api callbacks */ 06572 ot->invoke= ED_object_add_generic_invoke; 06573 ot->exec= add_primitive_bezier_circle_exec; 06574 ot->poll= ED_operator_scene_editable; 06575 06576 /* flags */ 06577 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06578 06579 ED_object_add_generic_props(ot, TRUE); 06580 } 06581 06582 static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op) 06583 { 06584 return curve_prim_add(C, op, CU_NURBS|CU_PRIM_CURVE); 06585 } 06586 06587 void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot) 06588 { 06589 /* identifiers */ 06590 ot->name= "Add Nurbs Curve"; 06591 ot->description= "Construct a Nurbs Curve"; 06592 ot->idname= "CURVE_OT_primitive_nurbs_curve_add"; 06593 06594 /* api callbacks */ 06595 ot->invoke= ED_object_add_generic_invoke; 06596 ot->exec= add_primitive_nurbs_curve_exec; 06597 ot->poll= ED_operator_scene_editable; 06598 06599 /* flags */ 06600 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06601 06602 ED_object_add_generic_props(ot, TRUE); 06603 } 06604 06605 static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op) 06606 { 06607 return curve_prim_add(C, op, CU_NURBS|CU_PRIM_CIRCLE); 06608 } 06609 06610 void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot) 06611 { 06612 /* identifiers */ 06613 ot->name= "Add Nurbs Circle"; 06614 ot->description= "Construct a Nurbs Circle"; 06615 ot->idname= "CURVE_OT_primitive_nurbs_circle_add"; 06616 06617 /* api callbacks */ 06618 ot->invoke= ED_object_add_generic_invoke; 06619 ot->exec= add_primitive_nurbs_circle_exec; 06620 ot->poll= ED_operator_scene_editable; 06621 06622 /* flags */ 06623 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06624 06625 ED_object_add_generic_props(ot, TRUE); 06626 } 06627 06628 static int add_primitive_curve_path_exec(bContext *C, wmOperator *op) 06629 { 06630 return curve_prim_add(C, op, CU_NURBS|CU_PRIM_PATH); 06631 } 06632 06633 void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot) 06634 { 06635 /* identifiers */ 06636 ot->name= "Add Path"; 06637 ot->description= "Construct a Path"; 06638 ot->idname= "CURVE_OT_primitive_nurbs_path_add"; 06639 06640 /* api callbacks */ 06641 ot->invoke= ED_object_add_generic_invoke; 06642 ot->exec= add_primitive_curve_path_exec; 06643 ot->poll= ED_operator_scene_editable; 06644 06645 /* flags */ 06646 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06647 06648 ED_object_add_generic_props(ot, TRUE); 06649 } 06650 06651 /* **************** NURBS surfaces ********************** */ 06652 static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op) 06653 { 06654 return surf_prim_add(C, op, CU_PRIM_CURVE|CU_NURBS); 06655 } 06656 06657 void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot) 06658 { 06659 /* identifiers */ 06660 ot->name= "Add Surface Curve"; 06661 ot->description= "Construct a Nurbs surface Curve"; 06662 ot->idname= "SURFACE_OT_primitive_nurbs_surface_curve_add"; 06663 06664 /* api callbacks */ 06665 ot->invoke= ED_object_add_generic_invoke; 06666 ot->exec= add_primitive_nurbs_surface_curve_exec; 06667 ot->poll= ED_operator_scene_editable; 06668 06669 /* flags */ 06670 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06671 06672 ED_object_add_generic_props(ot, TRUE); 06673 } 06674 06675 static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op) 06676 { 06677 return surf_prim_add(C, op, CU_PRIM_CIRCLE|CU_NURBS); 06678 } 06679 06680 void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot) 06681 { 06682 /* identifiers */ 06683 ot->name= "Add Surface Circle"; 06684 ot->description= "Construct a Nurbs surface Circle"; 06685 ot->idname= "SURFACE_OT_primitive_nurbs_surface_circle_add"; 06686 06687 /* api callbacks */ 06688 ot->invoke= ED_object_add_generic_invoke; 06689 ot->exec= add_primitive_nurbs_surface_circle_exec; 06690 ot->poll= ED_operator_scene_editable; 06691 06692 /* flags */ 06693 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06694 06695 ED_object_add_generic_props(ot, TRUE); 06696 } 06697 06698 static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op) 06699 { 06700 return surf_prim_add(C, op, CU_PRIM_PATCH|CU_NURBS); 06701 } 06702 06703 void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot) 06704 { 06705 /* identifiers */ 06706 ot->name= "Add Surface Patch"; 06707 ot->description= "Construct a Nurbs surface Patch"; 06708 ot->idname= "SURFACE_OT_primitive_nurbs_surface_surface_add"; 06709 06710 /* api callbacks */ 06711 ot->invoke= ED_object_add_generic_invoke; 06712 ot->exec= add_primitive_nurbs_surface_surface_exec; 06713 ot->poll= ED_operator_scene_editable; 06714 06715 /* flags */ 06716 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06717 06718 ED_object_add_generic_props(ot, TRUE); 06719 } 06720 06721 static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op) 06722 { 06723 return surf_prim_add(C, op, CU_PRIM_TUBE|CU_NURBS); 06724 } 06725 06726 void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot) 06727 { 06728 /* identifiers */ 06729 ot->name= "Add Surface Cylinder"; 06730 ot->description= "Construct a Nurbs surface Cylinder"; 06731 ot->idname= "SURFACE_OT_primitive_nurbs_surface_cylinder_add"; 06732 06733 /* api callbacks */ 06734 ot->invoke= ED_object_add_generic_invoke; 06735 ot->exec= add_primitive_nurbs_surface_cylinder_exec; 06736 ot->poll= ED_operator_scene_editable; 06737 06738 /* flags */ 06739 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06740 06741 ED_object_add_generic_props(ot, TRUE); 06742 } 06743 06744 static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op) 06745 { 06746 return surf_prim_add(C, op, CU_PRIM_SPHERE|CU_NURBS); 06747 } 06748 06749 void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot) 06750 { 06751 /* identifiers */ 06752 ot->name= "Add Surface Sphere"; 06753 ot->description= "Construct a Nurbs surface Sphere"; 06754 ot->idname= "SURFACE_OT_primitive_nurbs_surface_sphere_add"; 06755 06756 /* api callbacks */ 06757 ot->invoke= ED_object_add_generic_invoke; 06758 ot->exec= add_primitive_nurbs_surface_sphere_exec; 06759 ot->poll= ED_operator_scene_editable; 06760 06761 /* flags */ 06762 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06763 06764 ED_object_add_generic_props(ot, TRUE); 06765 } 06766 06767 static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op) 06768 { 06769 return surf_prim_add(C, op, CU_PRIM_DONUT|CU_NURBS); 06770 } 06771 06772 void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot) 06773 { 06774 /* identifiers */ 06775 ot->name= "Add Surface Torus"; 06776 ot->description= "Construct a Nurbs surface Torus"; 06777 ot->idname= "SURFACE_OT_primitive_nurbs_surface_torus_add"; 06778 06779 /* api callbacks */ 06780 ot->invoke= ED_object_add_generic_invoke; 06781 ot->exec= add_primitive_nurbs_surface_torus_exec; 06782 ot->poll= ED_operator_scene_editable; 06783 06784 /* flags */ 06785 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06786 06787 ED_object_add_generic_props(ot, TRUE); 06788 } 06789 06790 /***************** clear tilt operator ********************/ 06791 06792 static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) 06793 { 06794 Object *obedit= CTX_data_edit_object(C); 06795 Curve *cu= obedit->data; 06796 ListBase *editnurb= object_editcurve_get(obedit); 06797 Nurb *nu; 06798 BezTriple *bezt; 06799 BPoint *bp; 06800 int a; 06801 06802 for(nu= editnurb->first; nu; nu= nu->next) { 06803 if( nu->bezt ) { 06804 bezt= nu->bezt; 06805 a= nu->pntsu; 06806 while(a--) { 06807 if(BEZSELECTED_HIDDENHANDLES(cu, bezt)) bezt->alfa= 0.0; 06808 bezt++; 06809 } 06810 } 06811 else if(nu->bp) { 06812 bp= nu->bp; 06813 a= nu->pntsu*nu->pntsv; 06814 while(a--) { 06815 if(bp->f1 & SELECT) bp->alfa= 0.0; 06816 bp++; 06817 } 06818 } 06819 } 06820 06821 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 06822 DAG_id_tag_update(obedit->data, 0); 06823 06824 return OPERATOR_FINISHED; 06825 } 06826 06827 void CURVE_OT_tilt_clear(wmOperatorType *ot) 06828 { 06829 /* identifiers */ 06830 ot->name= "Clear Tilt"; 06831 ot->idname= "CURVE_OT_tilt_clear"; 06832 06833 /* api callbacks */ 06834 ot->exec= clear_tilt_exec; 06835 ot->poll= ED_operator_editcurve; 06836 06837 /* flags */ 06838 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 06839 } 06840 06841 /****************** undo for curves ****************/ 06842 06843 static void *undo_check_lastsel(void *lastsel, Nurb *nu, Nurb *newnu) 06844 { 06845 if (nu->bezt) { 06846 BezTriple *lastbezt= (BezTriple*)lastsel; 06847 if (lastbezt >= nu->bezt && lastbezt < nu->bezt + nu->pntsu) { 06848 return newnu->bezt + (lastbezt - nu->bezt); 06849 } 06850 } else { 06851 BPoint *lastbp= (BPoint*)lastsel; 06852 if (lastbp >= nu->bp && lastbp < nu->bp + nu->pntsu*nu->pntsv) { 06853 return newnu->bp + (lastbp - nu->bp); 06854 } 06855 } 06856 06857 return NULL; 06858 } 06859 06860 static void undoCurve_to_editCurve(void *ucu, void *obe) 06861 { 06862 Object *obedit= obe; 06863 Curve *cu= (Curve*)obedit->data; 06864 UndoCurve *undoCurve= ucu; 06865 ListBase *undobase= &undoCurve->nubase; 06866 ListBase *editbase= curve_editnurbs(cu); 06867 Nurb *nu, *newnu; 06868 EditNurb *editnurb= cu->editnurb; 06869 void *lastsel= NULL; 06870 AnimData *ad= BKE_animdata_from_id(&cu->id); 06871 06872 freeNurblist(editbase); 06873 06874 if (undoCurve->undoIndex) { 06875 BLI_ghash_free(editnurb->keyindex, NULL, (GHashValFreeFP)MEM_freeN); 06876 editnurb->keyindex= dupli_keyIndexHash(undoCurve->undoIndex); 06877 } 06878 06879 if(ad) { 06880 if(ad->action) { 06881 free_fcurves(&ad->action->curves); 06882 copy_fcurves(&ad->action->curves, &undoCurve->fcurves); 06883 } 06884 06885 free_fcurves(&ad->drivers); 06886 copy_fcurves(&ad->drivers, &undoCurve->drivers); 06887 } 06888 06889 /* copy */ 06890 for(nu= undobase->first; nu; nu= nu->next) { 06891 newnu= duplicateNurb(nu); 06892 06893 if (lastsel == NULL) { 06894 lastsel= undo_check_lastsel(undoCurve->lastsel, nu, newnu); 06895 } 06896 06897 if (editnurb->keyindex) { 06898 keyIndex_updateNurb(editnurb, nu, newnu); 06899 } 06900 06901 BLI_addtail(editbase, newnu); 06902 } 06903 06904 cu->lastsel= lastsel; 06905 cu->actnu= undoCurve->actnu; 06906 06907 ED_curve_updateAnimPaths(obedit); 06908 } 06909 06910 static void *editCurve_to_undoCurve(void *obe) 06911 { 06912 Object *obedit= obe; 06913 Curve *cu= (Curve*)obedit->data; 06914 ListBase *nubase= curve_editnurbs(cu); 06915 UndoCurve *undoCurve; 06916 EditNurb *editnurb= cu->editnurb, tmpEditnurb; 06917 Nurb *nu, *newnu; 06918 void *lastsel= NULL; 06919 AnimData *ad= BKE_animdata_from_id(&cu->id); 06920 06921 undoCurve= MEM_callocN(sizeof(UndoCurve), "undoCurve"); 06922 06923 if (editnurb->keyindex) { 06924 undoCurve->undoIndex= dupli_keyIndexHash(editnurb->keyindex); 06925 tmpEditnurb.keyindex= undoCurve->undoIndex; 06926 } 06927 06928 if(ad) { 06929 if(ad->action) 06930 copy_fcurves(&undoCurve->fcurves, &ad->action->curves); 06931 06932 copy_fcurves(&undoCurve->drivers, &ad->drivers); 06933 } 06934 06935 /* copy */ 06936 for(nu= nubase->first; nu; nu= nu->next) { 06937 newnu= duplicateNurb(nu); 06938 06939 if (lastsel == NULL) { 06940 lastsel= undo_check_lastsel(cu->lastsel, nu, newnu); 06941 } 06942 06943 if (undoCurve->undoIndex) { 06944 keyIndex_updateNurb(&tmpEditnurb, nu, newnu); 06945 } 06946 06947 BLI_addtail(&undoCurve->nubase, newnu); 06948 } 06949 06950 undoCurve->lastsel= lastsel; 06951 undoCurve->actnu= cu->actnu; 06952 06953 return undoCurve; 06954 } 06955 06956 static void free_undoCurve(void *ucv) 06957 { 06958 UndoCurve *undoCurve= ucv; 06959 06960 freeNurblist(&undoCurve->nubase); 06961 06962 if(undoCurve->undoIndex) 06963 BLI_ghash_free(undoCurve->undoIndex, NULL, (GHashValFreeFP)MEM_freeN); 06964 06965 free_fcurves(&undoCurve->fcurves); 06966 free_fcurves(&undoCurve->drivers); 06967 06968 MEM_freeN(undoCurve); 06969 } 06970 06971 static void *get_data(bContext *C) 06972 { 06973 Object *obedit= CTX_data_edit_object(C); 06974 return obedit; 06975 } 06976 06977 /* and this is all the undo system needs to know */ 06978 void undo_push_curve(bContext *C, const char *name) 06979 { 06980 undo_editmode_push(C, name, get_data, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve, NULL); 06981 } 06982 06983 void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count) 06984 { 06985 memcpy(dst, src, count*sizeof(BezTriple)); 06986 keyIndex_updateBezt(editnurb, src, dst, count); 06987 } 06988 06989 void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count) 06990 { 06991 memcpy(dst, src, count*sizeof(BPoint)); 06992 keyIndex_updateBP(editnurb, src, dst, count); 06993 } 06994 06995 int ED_curve_actSelection(Curve *cu, float center[3]) 06996 { 06997 Nurb *nu= get_lastsel_nurb(cu); 06998 06999 if(!nu) 07000 return 0; 07001 07002 if(nu->bezt) { 07003 BezTriple *bezt= cu->lastsel; 07004 07005 copy_v3_v3(center, bezt->vec[1]); 07006 } 07007 else { 07008 BPoint *bp= cu->lastsel; 07009 07010 copy_v3_v3(center, bp->vec); 07011 } 07012 07013 return 1; 07014 }