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