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