|
Blender
V2.59
|
00001 /* 00002 * $Id: object_select.c 36525 2011-05-06 23:46:24Z 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 * Contributor(s): Blender Foundation, 2002-2008 full recode 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <ctype.h> 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <string.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "DNA_group_types.h" 00041 #include "DNA_material_types.h" 00042 #include "DNA_modifier_types.h" 00043 #include "DNA_property_types.h" 00044 #include "DNA_scene_types.h" 00045 00046 #include "BLI_math.h" 00047 #include "BLI_listbase.h" 00048 #include "BLI_rand.h" 00049 #include "BLI_string.h" 00050 #include "BLI_utildefines.h" 00051 00052 #include "BKE_context.h" 00053 #include "BKE_group.h" 00054 #include "BKE_main.h" 00055 #include "BKE_material.h" 00056 #include "BKE_particle.h" 00057 #include "BKE_property.h" 00058 #include "BKE_report.h" 00059 #include "BKE_scene.h" 00060 #include "BKE_library.h" 00061 #include "BKE_deform.h" 00062 00063 #include "WM_api.h" 00064 #include "WM_types.h" 00065 00066 #include "ED_object.h" 00067 #include "ED_screen.h" 00068 00069 #include "UI_interface.h" 00070 #include "UI_resources.h" 00071 00072 #include "RNA_access.h" 00073 #include "RNA_define.h" 00074 #include "RNA_enum_types.h" 00075 00076 #include "object_intern.h" 00077 00078 /************************ Exported **************************/ 00079 00080 /* simple API for object selection, rather than just using the flag 00081 * this takes into account the 'restrict selection in 3d view' flag. 00082 * deselect works always, the restriction just prevents selection */ 00083 00084 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or 00085 * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */ 00086 00087 void ED_base_object_select(Base *base, short mode) 00088 { 00089 if (base) { 00090 if (mode==BA_SELECT) { 00091 if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) 00092 base->flag |= SELECT; 00093 } 00094 else if (mode==BA_DESELECT) { 00095 base->flag &= ~SELECT; 00096 } 00097 base->object->flag= base->flag; 00098 } 00099 } 00100 00101 /* also to set active NULL */ 00102 void ED_base_object_activate(bContext *C, Base *base) 00103 { 00104 Scene *scene= CTX_data_scene(C); 00105 00106 /* sets scene->basact */ 00107 BASACT= base; 00108 00109 if(base) { 00110 00111 /* XXX old signals, remember to handle notifiers now! */ 00112 // select_actionchannel_by_name(base->object->action, "Object", 1); 00113 00114 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); 00115 } 00116 else 00117 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL); 00118 } 00119 00120 /********************** Selection Operators **********************/ 00121 00122 /************************ Select by Type *************************/ 00123 00124 static int object_select_by_type_exec(bContext *C, wmOperator *op) 00125 { 00126 short obtype, extend; 00127 00128 obtype = RNA_enum_get(op->ptr, "type"); 00129 extend= RNA_boolean_get(op->ptr, "extend"); 00130 00131 if (extend == 0) { 00132 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00133 ED_base_object_select(base, BA_DESELECT); 00134 } 00135 CTX_DATA_END; 00136 } 00137 00138 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00139 if(base->object->type==obtype) { 00140 ED_base_object_select(base, BA_SELECT); 00141 } 00142 } 00143 CTX_DATA_END; 00144 00145 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00146 00147 return OPERATOR_FINISHED; 00148 } 00149 00150 void OBJECT_OT_select_by_type(wmOperatorType *ot) 00151 { 00152 /* identifiers */ 00153 ot->name= "Select By Type"; 00154 ot->description = "Select all visible objects that are of a type"; 00155 ot->idname= "OBJECT_OT_select_by_type"; 00156 00157 /* api callbacks */ 00158 ot->invoke= WM_menu_invoke; 00159 ot->exec= object_select_by_type_exec; 00160 ot->poll= ED_operator_objectmode; 00161 00162 /* flags */ 00163 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00164 00165 /* properties */ 00166 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); 00167 ot->prop= RNA_def_enum(ot->srna, "type", object_type_items, 1, "Type", ""); 00168 } 00169 00170 /*********************** Selection by Links *********************/ 00171 00172 static EnumPropertyItem prop_select_linked_types[] = { 00173 //{1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff... 00174 {2, "OBDATA", 0, "Object Data", ""}, 00175 {3, "MATERIAL", 0, "Material", ""}, 00176 {4, "TEXTURE", 0, "Texture", ""}, 00177 {5, "DUPGROUP", 0, "Dupligroup", ""}, 00178 {6, "PARTICLE", 0, "Particle System", ""}, 00179 {7, "LIBRARY", 0, "Library", ""}, 00180 {8, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""}, 00181 {0, NULL, 0, NULL, NULL} 00182 }; 00183 00184 static int object_select_linked_exec(bContext *C, wmOperator *op) 00185 { 00186 Scene *scene= CTX_data_scene(C); 00187 Object *ob; 00188 void *obdata = NULL; 00189 Material *mat = NULL, *mat1; 00190 Tex *tex= NULL; 00191 int a, b; 00192 int nr = RNA_enum_get(op->ptr, "type"); 00193 short changed = 0, extend; 00194 /* events (nr): 00195 * Object Ipo: 1 00196 * ObData: 2 00197 * Current Material: 3 00198 * Current Texture: 4 00199 * DupliGroup: 5 00200 * PSys: 6 00201 */ 00202 00203 extend= RNA_boolean_get(op->ptr, "extend"); 00204 00205 if (extend == 0) { 00206 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00207 ED_base_object_select(base, BA_DESELECT); 00208 } 00209 CTX_DATA_END; 00210 } 00211 00212 ob= OBACT; 00213 if(ob==NULL){ 00214 BKE_report(op->reports, RPT_ERROR, "No Active Object"); 00215 return OPERATOR_CANCELLED; 00216 } 00217 00218 if(nr==1) { 00219 // XXX old animation system 00220 //ipo= ob->ipo; 00221 //if(ipo==0) return OPERATOR_CANCELLED; 00222 return OPERATOR_CANCELLED; 00223 } 00224 else if(nr==2) { 00225 if(ob->data==NULL) return OPERATOR_CANCELLED; 00226 obdata= ob->data; 00227 } 00228 else if(nr==3 || nr==4) { 00229 mat= give_current_material(ob, ob->actcol); 00230 if(mat==NULL) return OPERATOR_CANCELLED; 00231 if(nr==4) { 00232 if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex; 00233 if(tex==NULL) return OPERATOR_CANCELLED; 00234 } 00235 } 00236 else if(nr==5) { 00237 if(ob->dup_group==NULL) return OPERATOR_CANCELLED; 00238 } 00239 else if(nr==6) { 00240 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED; 00241 } 00242 else if(nr==7) { 00243 /* do nothing */ 00244 } 00245 else if(nr==8) { 00246 if(ob->data==NULL) return OPERATOR_CANCELLED; 00247 } 00248 else 00249 return OPERATOR_CANCELLED; 00250 00251 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00252 if(nr==1) { 00253 // XXX old animation system 00254 //if(base->object->ipo==ipo) base->flag |= SELECT; 00255 //changed = 1; 00256 } 00257 else if(nr==2) { 00258 if(base->object->data==obdata) base->flag |= SELECT; 00259 changed = 1; 00260 } 00261 else if(nr==3 || nr==4) { 00262 ob= base->object; 00263 00264 for(a=1; a<=ob->totcol; a++) { 00265 mat1= give_current_material(ob, a); 00266 if(nr==3) { 00267 if(mat1==mat) base->flag |= SELECT; 00268 changed = 1; 00269 } 00270 else if(mat1 && nr==4) { 00271 for(b=0; b<MAX_MTEX; b++) { 00272 if(mat1->mtex[b]) { 00273 if(tex==mat1->mtex[b]->tex) { 00274 base->flag |= SELECT; 00275 changed = 1; 00276 break; 00277 } 00278 } 00279 } 00280 } 00281 } 00282 } 00283 else if(nr==5) { 00284 if(base->object->dup_group==ob->dup_group) { 00285 base->flag |= SELECT; 00286 changed = 1; 00287 } 00288 } 00289 else if(nr==6) { 00290 /* loop through other, then actives particles*/ 00291 ParticleSystem *psys; 00292 ParticleSystem *psys_act; 00293 00294 for(psys=base->object->particlesystem.first; psys; psys=psys->next) { 00295 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) { 00296 if (psys->part == psys_act->part) { 00297 base->flag |= SELECT; 00298 changed = 1; 00299 break; 00300 } 00301 } 00302 00303 if (base->flag & SELECT) { 00304 break; 00305 } 00306 } 00307 } 00308 else if(nr==7) { 00309 if(ob->id.lib == base->object->id.lib) { 00310 base->flag |= SELECT; 00311 changed= 1; 00312 } 00313 } 00314 else if(nr==8) { 00315 if(base->object->data && ((ID *)ob->data)->lib == ((ID *)base->object->data)->lib) { 00316 base->flag |= SELECT; 00317 changed= 1; 00318 } 00319 } 00320 base->object->flag= base->flag; 00321 } 00322 CTX_DATA_END; 00323 00324 if (changed) { 00325 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00326 return OPERATOR_FINISHED; 00327 } 00328 00329 return OPERATOR_CANCELLED; 00330 } 00331 00332 void OBJECT_OT_select_linked(wmOperatorType *ot) 00333 { 00334 /* identifiers */ 00335 ot->name= "Select Linked"; 00336 ot->description = "Select all visible objects that are linked"; 00337 ot->idname= "OBJECT_OT_select_linked"; 00338 00339 /* api callbacks */ 00340 ot->invoke= WM_menu_invoke; 00341 ot->exec= object_select_linked_exec; 00342 ot->poll= ED_operator_objectmode; 00343 00344 /* flags */ 00345 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00346 00347 /* properties */ 00348 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); 00349 ot->prop= RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", ""); 00350 } 00351 00352 /*********************** Selected Grouped ********************/ 00353 00354 static EnumPropertyItem prop_select_grouped_types[] = { 00355 {1, "CHILDREN_RECURSIVE", 0, "Children", ""}, 00356 {2, "CHILDREN", 0, "Immediate Children", ""}, 00357 {3, "PARENT", 0, "Parent", ""}, 00358 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"}, 00359 {5, "TYPE", 0, "Type", "Shared object type"}, 00360 {6, "LAYER", 0, "Layer", "Shared layers"}, 00361 {7, "GROUP", 0, "Group", "Shared group"}, 00362 {8, "HOOK", 0, "Hook", ""}, 00363 {9, "PASS", 0, "Pass", "Render pass Index"}, 00364 {10, "COLOR", 0, "Color", "Object Color"}, 00365 {11, "PROPERTIES", 0, "Properties", "Game Properties"}, 00366 {0, NULL, 0, NULL, NULL} 00367 }; 00368 00369 static short select_grouped_children(bContext *C, Object *ob, int recursive) 00370 { 00371 short changed = 0; 00372 00373 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00374 if (ob == base->object->parent) { 00375 if (!(base->flag & SELECT)) { 00376 ED_base_object_select(base, BA_SELECT); 00377 changed = 1; 00378 } 00379 00380 if (recursive) 00381 changed |= select_grouped_children(C, base->object, 1); 00382 } 00383 } 00384 CTX_DATA_END; 00385 return changed; 00386 } 00387 00388 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ 00389 { 00390 Scene *scene= CTX_data_scene(C); 00391 View3D *v3d= CTX_wm_view3d(C); 00392 00393 short changed = 0; 00394 Base *baspar, *basact= CTX_data_active_base(C); 00395 00396 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */ 00397 00398 baspar= object_in_scene(basact->object->parent, scene); 00399 00400 /* can be NULL if parent in other scene */ 00401 if(baspar && BASE_SELECTABLE(v3d, baspar)) { 00402 ED_base_object_select(basact, BA_DESELECT); 00403 ED_base_object_select(baspar, BA_SELECT); 00404 ED_base_object_activate(C, baspar); 00405 changed = 1; 00406 } 00407 return changed; 00408 } 00409 00410 00411 #define GROUP_MENU_MAX 24 00412 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */ 00413 { 00414 short changed = 0; 00415 Group *group, *ob_groups[GROUP_MENU_MAX]; 00416 int group_count=0, i; 00417 uiPopupMenu *pup; 00418 uiLayout *layout; 00419 00420 for (group=CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group=group->id.next) { 00421 if (object_in_group (ob, group)) { 00422 ob_groups[group_count] = group; 00423 group_count++; 00424 } 00425 } 00426 00427 if (!group_count) 00428 return 0; 00429 else if (group_count == 1) { 00430 group = ob_groups[0]; 00431 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00432 if (!(base->flag & SELECT) && object_in_group(base->object, group)) { 00433 ED_base_object_select(base, BA_SELECT); 00434 changed = 1; 00435 } 00436 } 00437 CTX_DATA_END; 00438 return changed; 00439 } 00440 00441 /* build the menu. */ 00442 pup= uiPupMenuBegin(C, "Select Group", ICON_NONE); 00443 layout= uiPupMenuLayout(pup); 00444 00445 for (i=0; i<group_count; i++) { 00446 group = ob_groups[i]; 00447 uiItemStringO(layout, group->id.name+2, 0, "OBJECT_OT_select_same_group", "group", group->id.name); 00448 } 00449 00450 uiPupMenuEnd(C, pup); 00451 return changed; // The operator already handle this! 00452 } 00453 00454 static short select_grouped_object_hooks(bContext *C, Object *ob) 00455 { 00456 Scene *scene= CTX_data_scene(C); 00457 View3D *v3d= CTX_wm_view3d(C); 00458 00459 short changed = 0; 00460 Base *base; 00461 ModifierData *md; 00462 HookModifierData *hmd; 00463 00464 for (md = ob->modifiers.first; md; md=md->next) { 00465 if (md->type==eModifierType_Hook) { 00466 hmd= (HookModifierData*) md; 00467 if (hmd->object && !(hmd->object->flag & SELECT)) { 00468 base= object_in_scene(hmd->object, scene); 00469 if (base && (BASE_SELECTABLE(v3d, base))) { 00470 ED_base_object_select(base, BA_SELECT); 00471 changed = 1; 00472 } 00473 } 00474 } 00475 } 00476 return changed; 00477 } 00478 00479 /* Select objects woth the same parent as the active (siblings), 00480 * parent can be NULL also */ 00481 static short select_grouped_siblings(bContext *C, Object *ob) 00482 { 00483 short changed = 0; 00484 00485 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00486 if ((base->object->parent==ob->parent) && !(base->flag & SELECT)) { 00487 ED_base_object_select(base, BA_SELECT); 00488 changed = 1; 00489 } 00490 } 00491 CTX_DATA_END; 00492 return changed; 00493 } 00494 00495 static short select_grouped_type(bContext *C, Object *ob) 00496 { 00497 short changed = 0; 00498 00499 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00500 if ((base->object->type == ob->type) && !(base->flag & SELECT)) { 00501 ED_base_object_select(base, BA_SELECT); 00502 changed = 1; 00503 } 00504 } 00505 CTX_DATA_END; 00506 return changed; 00507 } 00508 00509 static short select_grouped_layer(bContext *C, Object *ob) 00510 { 00511 char changed = 0; 00512 00513 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00514 if ((base->lay & ob->lay) && !(base->flag & SELECT)) { 00515 ED_base_object_select(base, BA_SELECT); 00516 changed = 1; 00517 } 00518 } 00519 CTX_DATA_END; 00520 return changed; 00521 } 00522 00523 static short select_grouped_index_object(bContext *C, Object *ob) 00524 { 00525 char changed = 0; 00526 00527 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00528 if ((base->object->index == ob->index) && !(base->flag & SELECT)) { 00529 ED_base_object_select(base, BA_SELECT); 00530 changed = 1; 00531 } 00532 } 00533 CTX_DATA_END; 00534 return changed; 00535 } 00536 00537 static short select_grouped_color(bContext *C, Object *ob) 00538 { 00539 char changed = 0; 00540 00541 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00542 if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) { 00543 ED_base_object_select(base, BA_SELECT); 00544 changed = 1; 00545 } 00546 } 00547 CTX_DATA_END; 00548 return changed; 00549 } 00550 00551 static short objects_share_gameprop(Object *a, Object *b) 00552 { 00553 bProperty *prop; 00554 /*make a copy of all its properties*/ 00555 00556 for( prop= a->prop.first; prop; prop = prop->next ) { 00557 if ( get_ob_property(b, prop->name) ) 00558 return 1; 00559 } 00560 return 0; 00561 } 00562 00563 static short select_grouped_gameprops(bContext *C, Object *ob) 00564 { 00565 char changed = 0; 00566 00567 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00568 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) { 00569 ED_base_object_select(base, BA_SELECT); 00570 changed = 1; 00571 } 00572 } 00573 CTX_DATA_END; 00574 return changed; 00575 } 00576 00577 static int object_select_grouped_exec(bContext *C, wmOperator *op) 00578 { 00579 Scene *scene= CTX_data_scene(C); 00580 Object *ob; 00581 int nr = RNA_enum_get(op->ptr, "type"); 00582 short changed = 0, extend; 00583 00584 extend= RNA_boolean_get(op->ptr, "extend"); 00585 00586 if (extend == 0) { 00587 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00588 ED_base_object_select(base, BA_DESELECT); 00589 changed = 1; 00590 } 00591 CTX_DATA_END; 00592 } 00593 00594 ob= OBACT; 00595 if(ob==NULL) { 00596 BKE_report(op->reports, RPT_ERROR, "No Active Object"); 00597 return OPERATOR_CANCELLED; 00598 } 00599 00600 if(nr==1) changed |= select_grouped_children(C, ob, 1); 00601 else if(nr==2) changed |= select_grouped_children(C, ob, 0); 00602 else if(nr==3) changed |= select_grouped_parent(C); 00603 else if(nr==4) changed |= select_grouped_siblings(C, ob); 00604 else if(nr==5) changed |= select_grouped_type(C, ob); 00605 else if(nr==6) changed |= select_grouped_layer(C, ob); 00606 else if(nr==7) changed |= select_grouped_group(C, ob); 00607 else if(nr==8) changed |= select_grouped_object_hooks(C, ob); 00608 else if(nr==9) changed |= select_grouped_index_object(C, ob); 00609 else if(nr==10) changed |= select_grouped_color(C, ob); 00610 else if(nr==11) changed |= select_grouped_gameprops(C, ob); 00611 00612 if (changed) { 00613 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00614 return OPERATOR_FINISHED; 00615 } 00616 00617 return OPERATOR_CANCELLED; 00618 } 00619 00620 void OBJECT_OT_select_grouped(wmOperatorType *ot) 00621 { 00622 /* identifiers */ 00623 ot->name= "Select Grouped"; 00624 ot->description = "Select all visible objects grouped by various properties"; 00625 ot->idname= "OBJECT_OT_select_grouped"; 00626 00627 /* api callbacks */ 00628 ot->invoke= WM_menu_invoke; 00629 ot->exec= object_select_grouped_exec; 00630 ot->poll= ED_operator_objectmode; 00631 00632 /* flags */ 00633 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00634 00635 /* properties */ 00636 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); 00637 ot->prop= RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); 00638 } 00639 00640 /************************* Select by Layer **********************/ 00641 00642 static int object_select_by_layer_exec(bContext *C, wmOperator *op) 00643 { 00644 unsigned int layernum; 00645 short extend; 00646 00647 extend= RNA_boolean_get(op->ptr, "extend"); 00648 layernum = RNA_int_get(op->ptr, "layers"); 00649 00650 if (extend == 0) { 00651 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00652 ED_base_object_select(base, BA_DESELECT); 00653 } 00654 CTX_DATA_END; 00655 } 00656 00657 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00658 if(base->lay == (1<< (layernum -1))) 00659 ED_base_object_select(base, BA_SELECT); 00660 } 00661 CTX_DATA_END; 00662 00663 /* undo? */ 00664 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00665 00666 return OPERATOR_FINISHED; 00667 } 00668 00669 void OBJECT_OT_select_by_layer(wmOperatorType *ot) 00670 { 00671 /* identifiers */ 00672 ot->name= "Select by Layer"; 00673 ot->description = "Select all visible objects on a layer"; 00674 ot->idname= "OBJECT_OT_select_by_layer"; 00675 00676 /* api callbacks */ 00677 /*ot->invoke = XXX - need a int grid popup*/ 00678 ot->exec= object_select_by_layer_exec; 00679 ot->poll= ED_operator_objectmode; 00680 00681 /* flags */ 00682 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00683 00684 /* properties */ 00685 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); 00686 RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20); 00687 } 00688 00689 /************************** Select Inverse *************************/ 00690 00691 static int object_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) 00692 { 00693 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00694 if (base->flag & SELECT) 00695 ED_base_object_select(base, BA_DESELECT); 00696 else 00697 ED_base_object_select(base, BA_SELECT); 00698 } 00699 CTX_DATA_END; 00700 00701 /* undo? */ 00702 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00703 00704 return OPERATOR_FINISHED; 00705 } 00706 00707 void OBJECT_OT_select_inverse(wmOperatorType *ot) 00708 { 00709 00710 /* identifiers */ 00711 ot->name= "Select Inverse"; 00712 ot->description = "Invert selection of all visible objects"; 00713 ot->idname= "OBJECT_OT_select_inverse"; 00714 00715 /* api callbacks */ 00716 ot->exec= object_select_inverse_exec; 00717 ot->poll= ED_operator_objectmode; 00718 00719 /* flags */ 00720 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00721 00722 } 00723 00724 /**************************** (De)select All ****************************/ 00725 00726 static int object_select_all_exec(bContext *C, wmOperator *op) 00727 { 00728 int action = RNA_enum_get(op->ptr, "action"); 00729 00730 /* passthrough if no objects are visible */ 00731 if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH; 00732 00733 if (action == SEL_TOGGLE) { 00734 action = SEL_SELECT; 00735 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00736 if (base->flag & SELECT) { 00737 action = SEL_DESELECT; 00738 break; 00739 } 00740 } 00741 CTX_DATA_END; 00742 } 00743 00744 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00745 switch (action) { 00746 case SEL_SELECT: 00747 ED_base_object_select(base, BA_SELECT); 00748 break; 00749 case SEL_DESELECT: 00750 ED_base_object_select(base, BA_DESELECT); 00751 break; 00752 case SEL_INVERT: 00753 if (base->flag & SELECT) { 00754 ED_base_object_select(base, BA_DESELECT); 00755 } else { 00756 ED_base_object_select(base, BA_SELECT); 00757 } 00758 break; 00759 } 00760 } 00761 CTX_DATA_END; 00762 00763 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00764 00765 return OPERATOR_FINISHED; 00766 } 00767 00768 void OBJECT_OT_select_all(wmOperatorType *ot) 00769 { 00770 00771 /* identifiers */ 00772 ot->name= "Select or Deselect All"; 00773 ot->description = "Change selection of all visible objects in scene"; 00774 ot->idname= "OBJECT_OT_select_all"; 00775 00776 /* api callbacks */ 00777 ot->exec= object_select_all_exec; 00778 ot->poll= ED_operator_objectmode; 00779 00780 /* flags */ 00781 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00782 00783 WM_operator_properties_select_all(ot); 00784 } 00785 00786 /**************************** Select In The Same Group ****************************/ 00787 00788 static int object_select_same_group_exec(bContext *C, wmOperator *op) 00789 { 00790 Group *group; 00791 char group_name[32]; 00792 00793 /* passthrough if no objects are visible */ 00794 if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH; 00795 00796 RNA_string_get(op->ptr, "group", group_name); 00797 00798 for (group=CTX_data_main(C)->group.first; group; group=group->id.next) { 00799 if (!strcmp(group->id.name, group_name)) 00800 break; 00801 } 00802 00803 if (!group) 00804 return OPERATOR_PASS_THROUGH; 00805 00806 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00807 if (!(base->flag & SELECT) && object_in_group(base->object, group)) 00808 ED_base_object_select(base, BA_SELECT); 00809 } 00810 CTX_DATA_END; 00811 00812 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00813 00814 return OPERATOR_FINISHED; 00815 } 00816 00817 void OBJECT_OT_select_same_group(wmOperatorType *ot) 00818 { 00819 00820 /* identifiers */ 00821 ot->name= "Select Same Group"; 00822 ot->description = "Select object in the same group"; 00823 ot->idname= "OBJECT_OT_select_same_group"; 00824 00825 /* api callbacks */ 00826 ot->exec= object_select_same_group_exec; 00827 ot->poll= ED_operator_objectmode; 00828 00829 /* flags */ 00830 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00831 00832 RNA_def_string(ot->srna, "group", "", 32, "Group", "Name of the group to select."); 00833 } 00834 00835 /**************************** Select Mirror ****************************/ 00836 static int object_select_mirror_exec(bContext *C, wmOperator *op) 00837 { 00838 Scene *scene= CTX_data_scene(C); 00839 short extend; 00840 00841 extend= RNA_boolean_get(op->ptr, "extend"); 00842 00843 CTX_DATA_BEGIN(C, Base*, primbase, selected_bases) { 00844 char tmpname[32]; 00845 00846 flip_side_name(tmpname, primbase->object->id.name+2, TRUE); 00847 00848 if(strcmp(tmpname, primbase->object->id.name+2)!=0) { /* names differ */ 00849 Object *ob= (Object *)find_id("OB", tmpname); 00850 if(ob) { 00851 Base *secbase= object_in_scene(ob, scene); 00852 00853 if(secbase) { 00854 ED_base_object_select(secbase, BA_SELECT); 00855 } 00856 } 00857 } 00858 00859 if (extend == 0) ED_base_object_select(primbase, BA_DESELECT); 00860 00861 } 00862 CTX_DATA_END; 00863 00864 /* undo? */ 00865 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00866 00867 return OPERATOR_FINISHED; 00868 } 00869 00870 void OBJECT_OT_select_mirror(wmOperatorType *ot) 00871 { 00872 00873 /* identifiers */ 00874 ot->name= "Select Mirror"; 00875 ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword"; 00876 ot->idname= "OBJECT_OT_select_mirror"; 00877 00878 /* api callbacks */ 00879 ot->exec= object_select_mirror_exec; 00880 ot->poll= ED_operator_objectmode; 00881 00882 /* flags */ 00883 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00884 00885 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); 00886 } 00887 00888 00889 static int object_select_name_exec(bContext *C, wmOperator *op) 00890 { 00891 char *name= RNA_string_get_alloc(op->ptr, "name", NULL, 0); 00892 short extend= RNA_boolean_get(op->ptr, "extend"); 00893 short changed = 0; 00894 00895 if(!extend) { 00896 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00897 if(base->flag & SELECT) { 00898 ED_base_object_select(base, BA_DESELECT); 00899 changed= 1; 00900 } 00901 } 00902 CTX_DATA_END; 00903 } 00904 00905 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { 00906 /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ 00907 if(strcmp(name, base->object->id.name+2)==0) { 00908 ED_base_object_activate(C, base); 00909 ED_base_object_select(base, BA_SELECT); 00910 changed= 1; 00911 } 00912 } 00913 CTX_DATA_END; 00914 00915 MEM_freeN(name); 00916 00917 /* undo? */ 00918 if(changed) { 00919 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00920 return OPERATOR_FINISHED; 00921 } 00922 else { 00923 return OPERATOR_CANCELLED; 00924 } 00925 } 00926 00927 void OBJECT_OT_select_name(wmOperatorType *ot) 00928 { 00929 00930 /* identifiers */ 00931 ot->name= "Select Name"; 00932 ot->description = "Select an object with this name"; 00933 ot->idname= "OBJECT_OT_select_name"; 00934 00935 /* api callbacks */ 00936 ot->exec= object_select_name_exec; 00937 ot->poll= ED_operator_objectmode; 00938 00939 /* flags */ 00940 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00941 00942 RNA_def_string(ot->srna, "name", "", 0, "Name", "Object name to select."); 00943 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); 00944 } 00945 00946 /**************************** Select Random ****************************/ 00947 00948 static int object_select_random_exec(bContext *C, wmOperator *op) 00949 { 00950 float percent; 00951 short extend; 00952 00953 extend= RNA_boolean_get(op->ptr, "extend"); 00954 00955 if (extend == 0) { 00956 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00957 ED_base_object_select(base, BA_DESELECT); 00958 } 00959 CTX_DATA_END; 00960 } 00961 percent = RNA_float_get(op->ptr, "percent")/100.0f; 00962 00963 CTX_DATA_BEGIN(C, Base*, base, visible_bases) { 00964 if (BLI_frand() < percent) { 00965 ED_base_object_select(base, BA_SELECT); 00966 } 00967 } 00968 CTX_DATA_END; 00969 00970 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); 00971 00972 return OPERATOR_FINISHED; 00973 } 00974 00975 void OBJECT_OT_select_random(wmOperatorType *ot) 00976 { 00977 /* identifiers */ 00978 ot->name= "Select Random"; 00979 ot->description = "Set select on random visible objects"; 00980 ot->idname= "OBJECT_OT_select_random"; 00981 00982 /* api callbacks */ 00983 /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/ 00984 ot->exec = object_select_random_exec; 00985 ot->poll= ED_operator_objectmode; 00986 00987 /* flags */ 00988 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00989 00990 /* properties */ 00991 RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of objects to select randomly", 0.f, 100.0f); 00992 RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first."); 00993 } 00994 00995