Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <math.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "BLI_blenlib.h" 00039 #include "BLI_math.h" 00040 #include "BLI_rand.h" 00041 #include "BLI_utildefines.h" 00042 00043 #include "DNA_defs.h" 00044 #include "DNA_meta_types.h" 00045 #include "DNA_object_types.h" 00046 #include "DNA_scene_types.h" 00047 00048 #include "RNA_define.h" 00049 #include "RNA_access.h" 00050 #include "RNA_enum_types.h" 00051 00052 #include "BKE_depsgraph.h" 00053 #include "BKE_context.h" 00054 #include "BKE_mball.h" 00055 00056 #include "ED_mball.h" 00057 #include "ED_screen.h" 00058 #include "ED_view3d.h" 00059 #include "ED_transform.h" 00060 #include "ED_util.h" 00061 00062 #include "WM_api.h" 00063 #include "WM_types.h" 00064 00065 #include "mball_intern.h" 00066 00067 /* This function is used to free all MetaElems from MetaBall */ 00068 void free_editMball(Object *obedit) 00069 { 00070 MetaBall *mb = (MetaBall*)obedit->data; 00071 00072 mb->editelems= NULL; 00073 mb->lastelem= NULL; 00074 } 00075 00076 /* This function is called, when MetaBall Object is 00077 * switched from object mode to edit mode */ 00078 void make_editMball(Object *obedit) 00079 { 00080 MetaBall *mb = (MetaBall*)obedit->data; 00081 MetaElem *ml;/*, *newml;*/ 00082 00083 ml= mb->elems.first; 00084 00085 while(ml) { 00086 if(ml->flag & SELECT) mb->lastelem = ml; 00087 ml= ml->next; 00088 } 00089 00090 mb->editelems = &mb->elems; 00091 } 00092 00093 /* This function is called, when MetaBall Object switched from 00094 * edit mode to object mode. List od MetaElements is copied 00095 * from object->data->edit_elems to object->data->elems. */ 00096 void load_editMball(Object *UNUSED(obedit)) 00097 { 00098 } 00099 00100 /* Add metaelem primitive to metaball object (which is in edit mode) */ 00101 MetaElem *add_metaball_primitive(bContext *C, float mat[4][4], int type, int UNUSED(newname)) 00102 { 00103 Object *obedit= CTX_data_edit_object(C); 00104 MetaBall *mball = (MetaBall*)obedit->data; 00105 MetaElem *ml; 00106 00107 /* Deselect all existing metaelems */ 00108 ml= mball->editelems->first; 00109 while(ml) { 00110 ml->flag &= ~SELECT; 00111 ml= ml->next; 00112 } 00113 00114 ml= add_metaball_element(mball, type); 00115 copy_v3_v3(&ml->x, mat[3]); 00116 00117 ml->flag |= SELECT; 00118 mball->lastelem= ml; 00119 return ml; 00120 } 00121 00122 /***************************** Select/Deselect operator *****************************/ 00123 00124 /* Select or deselect all MetaElements */ 00125 static int mball_select_all_exec(bContext *C, wmOperator *op) 00126 { 00127 //Scene *scene= CTX_data_scene(C); 00128 Object *obedit= CTX_data_edit_object(C); 00129 MetaBall *mb = (MetaBall*)obedit->data; 00130 MetaElem *ml; 00131 int action = RNA_enum_get(op->ptr, "action"); 00132 00133 ml= mb->editelems->first; 00134 if(ml) { 00135 if (action == SEL_TOGGLE) { 00136 action = SEL_SELECT; 00137 while(ml) { 00138 if(ml->flag & SELECT) { 00139 action = SEL_DESELECT; 00140 break; 00141 } 00142 ml= ml->next; 00143 } 00144 } 00145 00146 ml= mb->editelems->first; 00147 while(ml) { 00148 switch (action) { 00149 case SEL_SELECT: 00150 ml->flag |= SELECT; 00151 break; 00152 case SEL_DESELECT: 00153 ml->flag &= ~SELECT; 00154 break; 00155 case SEL_INVERT: 00156 ml->flag ^= SELECT; 00157 break; 00158 } 00159 ml= ml->next; 00160 } 00161 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, mb); 00162 } 00163 00164 return OPERATOR_FINISHED; 00165 } 00166 00167 void MBALL_OT_select_all(wmOperatorType *ot) 00168 { 00169 /* identifiers */ 00170 ot->name= "Select or Deselect All"; 00171 ot->description= "Change selection of all meta elements"; 00172 ot->idname= "MBALL_OT_select_all"; 00173 00174 /* callback functions */ 00175 ot->exec= mball_select_all_exec; 00176 ot->poll= ED_operator_editmball; 00177 00178 /* flags */ 00179 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00180 00181 WM_operator_properties_select_all(ot); 00182 } 00183 00184 /***************************** Select random operator *****************************/ 00185 00186 /* Random metaball selection */ 00187 static int select_random_metaelems_exec(bContext *C, wmOperator *op) 00188 { 00189 Object *obedit= CTX_data_edit_object(C); 00190 MetaBall *mb = (MetaBall*)obedit->data; 00191 MetaElem *ml; 00192 float percent= RNA_float_get(op->ptr, "percent"); 00193 00194 if(percent == 0.0f) 00195 return OPERATOR_CANCELLED; 00196 00197 ml= mb->editelems->first; 00198 BLI_srand( BLI_rand() ); /* Random seed */ 00199 00200 /* Stupid version of random selection. Should be improved. */ 00201 while(ml) { 00202 if(BLI_frand() < percent) 00203 ml->flag |= SELECT; 00204 else 00205 ml->flag &= ~SELECT; 00206 ml= ml->next; 00207 } 00208 00209 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, mb); 00210 00211 return OPERATOR_FINISHED; 00212 } 00213 00214 00215 void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot) 00216 { 00217 /* identifiers */ 00218 ot->name= "Random..."; 00219 ot->description= "Randomly select metaelements"; 00220 ot->idname= "MBALL_OT_select_random_metaelems"; 00221 00222 /* callback functions */ 00223 ot->exec= select_random_metaelems_exec; 00224 ot->invoke= WM_operator_props_popup; 00225 ot->poll= ED_operator_editmball; 00226 00227 /* flags */ 00228 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00229 00230 /* properties */ 00231 RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of metaelems to select randomly", 0.0001f, 1.0f); 00232 } 00233 00234 /***************************** Duplicate operator *****************************/ 00235 00236 /* Duplicate selected MetaElements */ 00237 static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) 00238 { 00239 Object *obedit= CTX_data_edit_object(C); 00240 MetaBall *mb = (MetaBall*)obedit->data; 00241 MetaElem *ml, *newml; 00242 00243 ml= mb->editelems->last; 00244 if(ml) { 00245 while(ml) { 00246 if(ml->flag & SELECT) { 00247 newml= MEM_dupallocN(ml); 00248 BLI_addtail(mb->editelems, newml); 00249 mb->lastelem= newml; 00250 ml->flag &= ~SELECT; 00251 } 00252 ml= ml->prev; 00253 } 00254 WM_event_add_notifier(C, NC_GEOM|ND_DATA, mb); 00255 DAG_id_tag_update(obedit->data, 0); 00256 } 00257 00258 return OPERATOR_FINISHED; 00259 } 00260 00261 static int duplicate_metaelems_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00262 { 00263 int retv= duplicate_metaelems_exec(C, op); 00264 00265 if (retv == OPERATOR_FINISHED) { 00266 RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION); 00267 WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); 00268 } 00269 00270 return retv; 00271 } 00272 00273 00274 void MBALL_OT_duplicate_metaelems(wmOperatorType *ot) 00275 { 00276 /* identifiers */ 00277 ot->name= "Duplicate Metaelements"; 00278 ot->description= "Delete selected metaelement(s)"; 00279 ot->idname= "MBALL_OT_duplicate_metaelems"; 00280 00281 /* callback functions */ 00282 ot->exec= duplicate_metaelems_exec; 00283 ot->invoke= duplicate_metaelems_invoke; 00284 ot->poll= ED_operator_editmball; 00285 00286 /* flags */ 00287 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00288 00289 /* to give to transform */ 00290 RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); 00291 } 00292 00293 /***************************** Delete operator *****************************/ 00294 00295 /* Delete all selected MetaElems (not MetaBall) */ 00296 static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) 00297 { 00298 Object *obedit= CTX_data_edit_object(C); 00299 MetaBall *mb= (MetaBall*)obedit->data; 00300 MetaElem *ml, *next; 00301 00302 ml= mb->editelems->first; 00303 if(ml) { 00304 while(ml) { 00305 next= ml->next; 00306 if(ml->flag & SELECT) { 00307 if(mb->lastelem==ml) mb->lastelem= NULL; 00308 BLI_remlink(mb->editelems, ml); 00309 MEM_freeN(ml); 00310 } 00311 ml= next; 00312 } 00313 WM_event_add_notifier(C, NC_GEOM|ND_DATA, mb); 00314 DAG_id_tag_update(obedit->data, 0); 00315 } 00316 00317 return OPERATOR_FINISHED; 00318 } 00319 00320 void MBALL_OT_delete_metaelems(wmOperatorType *ot) 00321 { 00322 /* identifiers */ 00323 ot->name= "Delete"; 00324 ot->description= "Delete selected metaelement(s)"; 00325 ot->idname= "MBALL_OT_delete_metaelems"; 00326 00327 /* callback functions */ 00328 ot->exec= delete_metaelems_exec; 00329 ot->poll= ED_operator_editmball; 00330 00331 /* flags */ 00332 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00333 } 00334 00335 /***************************** Hide operator *****************************/ 00336 00337 /* Hide selected MetaElems */ 00338 static int hide_metaelems_exec(bContext *C, wmOperator *op) 00339 { 00340 Object *obedit= CTX_data_edit_object(C); 00341 MetaBall *mb= (MetaBall*)obedit->data; 00342 MetaElem *ml; 00343 const int invert= RNA_boolean_get(op->ptr, "unselected") ? SELECT : 0; 00344 00345 ml= mb->editelems->first; 00346 00347 if(ml) { 00348 while(ml){ 00349 if((ml->flag & SELECT) != invert) 00350 ml->flag |= MB_HIDE; 00351 ml= ml->next; 00352 } 00353 WM_event_add_notifier(C, NC_GEOM|ND_DATA, mb); 00354 DAG_id_tag_update(obedit->data, 0); 00355 } 00356 00357 return OPERATOR_FINISHED; 00358 } 00359 00360 void MBALL_OT_hide_metaelems(wmOperatorType *ot) 00361 { 00362 /* identifiers */ 00363 ot->name= "Hide"; 00364 ot->description= "Hide (un)selected metaelement(s)"; 00365 ot->idname= "MBALL_OT_hide_metaelems"; 00366 00367 /* callback functions */ 00368 ot->exec= hide_metaelems_exec; 00369 ot->poll= ED_operator_editmball; 00370 00371 /* flags */ 00372 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00373 00374 /* props */ 00375 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); 00376 } 00377 00378 /***************************** Unhide operator *****************************/ 00379 00380 /* Unhide all edited MetaElems */ 00381 static int reveal_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) 00382 { 00383 Object *obedit= CTX_data_edit_object(C); 00384 MetaBall *mb= (MetaBall*)obedit->data; 00385 MetaElem *ml; 00386 00387 ml= mb->editelems->first; 00388 00389 if(ml) { 00390 while(ml) { 00391 ml->flag &= ~MB_HIDE; 00392 ml= ml->next; 00393 } 00394 WM_event_add_notifier(C, NC_GEOM|ND_DATA, mb); 00395 DAG_id_tag_update(obedit->data, 0); 00396 } 00397 00398 return OPERATOR_FINISHED; 00399 } 00400 00401 void MBALL_OT_reveal_metaelems(wmOperatorType *ot) 00402 { 00403 /* identifiers */ 00404 ot->name= "Reveal"; 00405 ot->description= "Reveal all hidden metaelements"; 00406 ot->idname= "MBALL_OT_reveal_metaelems"; 00407 00408 /* callback functions */ 00409 ot->exec= reveal_metaelems_exec; 00410 ot->poll= ED_operator_editmball; 00411 00412 /* flags */ 00413 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00414 } 00415 00416 /* Select MetaElement with mouse click (user can select radius circle or 00417 * stiffness circle) */ 00418 int mouse_mball(bContext *C, const int mval[2], int extend) 00419 { 00420 static MetaElem *startelem=NULL; 00421 Object *obedit= CTX_data_edit_object(C); 00422 ViewContext vc; 00423 MetaBall *mb = (MetaBall*)obedit->data; 00424 MetaElem *ml, *act=NULL; 00425 int a, hits; 00426 unsigned int buffer[4*MAXPICKBUF]; 00427 rcti rect; 00428 00429 view3d_set_viewcontext(C, &vc); 00430 00431 rect.xmin= mval[0]-12; 00432 rect.xmax= mval[0]+12; 00433 rect.ymin= mval[1]-12; 00434 rect.ymax= mval[1]+12; 00435 00436 hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect); 00437 00438 /* does startelem exist? */ 00439 ml= mb->editelems->first; 00440 while(ml) { 00441 if(ml==startelem) break; 00442 ml= ml->next; 00443 } 00444 00445 if(ml==NULL) startelem= mb->editelems->first; 00446 00447 if(hits>0) { 00448 ml= startelem; 00449 while(ml) { 00450 for(a=0; a<hits; a++) { 00451 /* index converted for gl stuff */ 00452 if(ml->selcol1==buffer[ 4 * a + 3 ]){ 00453 ml->flag |= MB_SCALE_RAD; 00454 act= ml; 00455 } 00456 if(ml->selcol2==buffer[ 4 * a + 3 ]){ 00457 ml->flag &= ~MB_SCALE_RAD; 00458 act= ml; 00459 } 00460 } 00461 if(act) break; 00462 ml= ml->next; 00463 if(ml==NULL) ml= mb->editelems->first; 00464 if(ml==startelem) break; 00465 } 00466 00467 /* When some metaelem was found, then it is necessary to select or 00468 * deselet it. */ 00469 if(act) { 00470 if(extend==0) { 00471 /* Deselect all existing metaelems */ 00472 ml= mb->editelems->first; 00473 while(ml) { 00474 ml->flag &= ~SELECT; 00475 ml= ml->next; 00476 } 00477 /* Select only metaelem clicked on */ 00478 act->flag |= SELECT; 00479 } 00480 else { 00481 if(act->flag & SELECT) 00482 act->flag &= ~SELECT; 00483 else 00484 act->flag |= SELECT; 00485 } 00486 mb->lastelem= act; 00487 00488 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, mb); 00489 00490 return 1; 00491 } 00492 } 00493 00494 return 0; 00495 } 00496 00497 00498 /* ************* undo for MetaBalls ************* */ 00499 00500 /* free all MetaElems from ListBase */ 00501 static void freeMetaElemlist(ListBase *lb) 00502 { 00503 MetaElem *ml, *next; 00504 00505 if(lb==NULL) return; 00506 00507 ml= lb->first; 00508 while(ml){ 00509 next= ml->next; 00510 BLI_remlink(lb, ml); 00511 MEM_freeN(ml); 00512 ml= next; 00513 } 00514 00515 lb->first= lb->last= NULL; 00516 } 00517 00518 00519 static void undoMball_to_editMball(void *lbu, void *lbe) 00520 { 00521 ListBase *lb= lbu; 00522 ListBase *editelems= lbe; 00523 MetaElem *ml, *newml; 00524 00525 freeMetaElemlist(editelems); 00526 00527 /* copy 'undo' MetaElems to 'edit' MetaElems */ 00528 ml= lb->first; 00529 while(ml){ 00530 newml= MEM_dupallocN(ml); 00531 BLI_addtail(editelems, newml); 00532 ml= ml->next; 00533 } 00534 00535 } 00536 00537 static void *editMball_to_undoMball(void *lbe) 00538 { 00539 ListBase *editelems= lbe; 00540 ListBase *lb; 00541 MetaElem *ml, *newml; 00542 00543 /* allocate memory for undo ListBase */ 00544 lb= MEM_callocN(sizeof(ListBase), "listbase undo"); 00545 lb->first= lb->last= NULL; 00546 00547 /* copy contents of current ListBase to the undo ListBase */ 00548 ml= editelems->first; 00549 while(ml){ 00550 newml= MEM_dupallocN(ml); 00551 BLI_addtail(lb, newml); 00552 ml= ml->next; 00553 } 00554 00555 return lb; 00556 } 00557 00558 /* free undo ListBase of MetaElems */ 00559 static void free_undoMball(void *lbv) 00560 { 00561 ListBase *lb= lbv; 00562 00563 freeMetaElemlist(lb); 00564 MEM_freeN(lb); 00565 } 00566 00567 static ListBase *metaball_get_editelems(Object *ob) 00568 { 00569 if(ob && ob->type==OB_MBALL) { 00570 struct MetaBall *mb= (struct MetaBall*)ob->data; 00571 return mb->editelems; 00572 } 00573 return NULL; 00574 } 00575 00576 00577 static void *get_data(bContext *C) 00578 { 00579 Object *obedit= CTX_data_edit_object(C); 00580 return metaball_get_editelems(obedit); 00581 } 00582 00583 /* this is undo system for MetaBalls */ 00584 void undo_push_mball(bContext *C, const char *name) 00585 { 00586 undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL); 00587 } 00588