|
Blender
V2.59
|
00001 /* 00002 * $Id: outliner_select.c 39294 2011-08-11 06:40:04Z gsrb3d $ 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) 2004 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Joshua Leung 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00034 #include <math.h> 00035 #include <string.h> 00036 #include <stdlib.h> 00037 #include <stddef.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "DNA_anim_types.h" 00042 #include "DNA_armature_types.h" 00043 #include "DNA_constraint_types.h" 00044 #include "DNA_camera_types.h" 00045 #include "DNA_group_types.h" 00046 #include "DNA_key_types.h" 00047 #include "DNA_lamp_types.h" 00048 #include "DNA_material_types.h" 00049 #include "DNA_mesh_types.h" 00050 #include "DNA_meta_types.h" 00051 #include "DNA_particle_types.h" 00052 #include "DNA_scene_types.h" 00053 #include "DNA_world_types.h" 00054 #include "DNA_sequence_types.h" 00055 #include "DNA_object_types.h" 00056 00057 #include "BLI_blenlib.h" 00058 #include "BLI_utildefines.h" 00059 #include "BLI_math_base.h" 00060 00061 #if defined WIN32 && !defined _LIBC 00062 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ 00063 #else 00064 # ifndef _GNU_SOURCE 00065 # define _GNU_SOURCE 00066 # endif 00067 # include <fnmatch.h> 00068 #endif 00069 00070 00071 #include "BKE_animsys.h" 00072 #include "BKE_context.h" 00073 #include "BKE_deform.h" 00074 #include "BKE_depsgraph.h" 00075 #include "BKE_fcurve.h" 00076 #include "BKE_global.h" 00077 #include "BKE_group.h" 00078 #include "BKE_library.h" 00079 #include "BKE_main.h" 00080 #include "BKE_modifier.h" 00081 #include "BKE_report.h" 00082 #include "BKE_scene.h" 00083 #include "BKE_sequencer.h" 00084 00085 #include "ED_armature.h" 00086 #include "ED_object.h" 00087 #include "ED_screen.h" 00088 #include "ED_util.h" 00089 00090 #include "WM_api.h" 00091 #include "WM_types.h" 00092 00093 #include "BIF_gl.h" 00094 #include "BIF_glutil.h" 00095 00096 #include "UI_interface.h" 00097 #include "UI_interface_icons.h" 00098 #include "UI_resources.h" 00099 #include "UI_view2d.h" 00100 00101 #include "RNA_access.h" 00102 #include "RNA_define.h" 00103 00104 #include "outliner_intern.h" 00105 00106 /* ****************************************************** */ 00107 /* Outliner Selection (grey-blue highlight for rows) */ 00108 00109 void outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting) 00110 { 00111 TreeElement *te; 00112 TreeStoreElem *tselem; 00113 00114 for (te= lb->first; te && *index >= 0; te=te->next, (*index)--) { 00115 tselem= TREESTORE(te); 00116 00117 /* if we've encountered the right item, set its 'Outliner' selection status */ 00118 if (*index == 0) { 00119 /* this should be the last one, so no need to do anything with index */ 00120 if ((te->flag & TE_ICONROW)==0) { 00121 /* -1 value means toggle testing for now... */ 00122 if (*selecting == -1) { 00123 if (tselem->flag & TSE_SELECTED) 00124 *selecting= 0; 00125 else 00126 *selecting= 1; 00127 } 00128 00129 /* set selection */ 00130 if (*selecting) 00131 tselem->flag |= TSE_SELECTED; 00132 else 00133 tselem->flag &= ~TSE_SELECTED; 00134 } 00135 } 00136 else if ((tselem->flag & TSE_CLOSED)==0) { 00137 /* Only try selecting sub-elements if we haven't hit the right element yet 00138 * 00139 * Hack warning: 00140 * Index must be reduced before supplying it to the sub-tree to try to do 00141 * selection, however, we need to increment it again for the next loop to 00142 * function correctly 00143 */ 00144 (*index)--; 00145 outliner_select(soops, &te->subtree, index, selecting); 00146 (*index)++; 00147 } 00148 } 00149 } 00150 00151 /* ****************************************************** */ 00152 /* Outliner Element Selection/Activation on Click */ 00153 00154 static int tree_element_active_renderlayer(bContext *C, TreeElement *te, TreeStoreElem *tselem, int set) 00155 { 00156 Scene *sce; 00157 00158 /* paranoia check */ 00159 if(te->idcode!=ID_SCE) 00160 return 0; 00161 sce= (Scene *)tselem->id; 00162 00163 if(set) { 00164 sce->r.actlay= tselem->nr; 00165 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, sce); 00166 } 00167 else { 00168 return sce->r.actlay==tselem->nr; 00169 } 00170 return 0; 00171 } 00172 00173 static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00174 { 00175 TreeStoreElem *tselem= TREESTORE(te); 00176 Scene *sce; 00177 Base *base; 00178 Object *ob= NULL; 00179 00180 /* if id is not object, we search back */ 00181 if(te->idcode==ID_OB) ob= (Object *)tselem->id; 00182 else { 00183 ob= (Object *)outliner_search_back(soops, te, ID_OB); 00184 if(ob==OBACT) return 0; 00185 } 00186 if(ob==NULL) return 0; 00187 00188 sce= (Scene *)outliner_search_back(soops, te, ID_SCE); 00189 if(sce && scene != sce) { 00190 ED_screen_set_scene(C, sce); 00191 } 00192 00193 /* find associated base in current scene */ 00194 base= object_in_scene(ob, scene); 00195 00196 if(base) { 00197 if(set==2) { 00198 /* swap select */ 00199 if(base->flag & SELECT) 00200 ED_base_object_select(base, BA_DESELECT); 00201 else 00202 ED_base_object_select(base, BA_SELECT); 00203 } 00204 else { 00205 /* deleselect all */ 00206 scene_deselect_all(scene); 00207 ED_base_object_select(base, BA_SELECT); 00208 } 00209 if(C) { 00210 ED_base_object_activate(C, base); /* adds notifier */ 00211 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); 00212 } 00213 } 00214 00215 if(ob!=scene->obedit) 00216 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO); 00217 00218 return 1; 00219 } 00220 00221 static int tree_element_active_material(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00222 { 00223 TreeElement *tes; 00224 Object *ob; 00225 00226 /* we search for the object parent */ 00227 ob= (Object *)outliner_search_back(soops, te, ID_OB); 00228 // note: ob->matbits can be NULL when a local object points to a library mesh. 00229 if(ob==NULL || ob!=OBACT || ob->matbits==NULL) return 0; // just paranoia 00230 00231 /* searching in ob mat array? */ 00232 tes= te->parent; 00233 if(tes->idcode==ID_OB) { 00234 if(set) { 00235 ob->actcol= te->index+1; 00236 ob->matbits[te->index]= 1; // make ob material active too 00237 ob->colbits |= (1<<te->index); 00238 } 00239 else { 00240 if(ob->actcol == te->index+1) 00241 if(ob->matbits[te->index]) return 1; 00242 } 00243 } 00244 /* or we search for obdata material */ 00245 else { 00246 if(set) { 00247 ob->actcol= te->index+1; 00248 ob->matbits[te->index]= 0; // make obdata material active too 00249 ob->colbits &= ~(1<<te->index); 00250 } 00251 else { 00252 if(ob->actcol == te->index+1) 00253 if(ob->matbits[te->index]==0) return 1; 00254 } 00255 } 00256 if(set) { 00257 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, NULL); 00258 } 00259 return 0; 00260 } 00261 00262 static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00263 { 00264 TreeElement *tep; 00265 TreeStoreElem /* *tselem,*/ *tselemp; 00266 Object *ob=OBACT; 00267 SpaceButs *sbuts=NULL; 00268 00269 if(ob==NULL) return 0; // no active object 00270 00271 /*tselem= TREESTORE(te);*/ /*UNUSED*/ 00272 00273 /* find buttons area (note, this is undefined really still, needs recode in blender) */ 00274 /* XXX removed finding sbuts */ 00275 00276 /* where is texture linked to? */ 00277 tep= te->parent; 00278 tselemp= TREESTORE(tep); 00279 00280 if(tep->idcode==ID_WO) { 00281 World *wrld= (World *)tselemp->id; 00282 00283 if(set) { 00284 if(sbuts) { 00285 // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c 00286 // XXX sbuts->texfrom= 1; 00287 } 00288 // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture 00289 wrld->texact= te->index; 00290 } 00291 else if(tselemp->id == (ID *)(scene->world)) { 00292 if(wrld->texact==te->index) return 1; 00293 } 00294 } 00295 else if(tep->idcode==ID_LA) { 00296 Lamp *la= (Lamp *)tselemp->id; 00297 if(set) { 00298 if(sbuts) { 00299 // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c 00300 // XXX sbuts->texfrom= 2; 00301 } 00302 // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture 00303 la->texact= te->index; 00304 } 00305 else { 00306 if(tselemp->id == ob->data) { 00307 if(la->texact==te->index) return 1; 00308 } 00309 } 00310 } 00311 else if(tep->idcode==ID_MA) { 00312 Material *ma= (Material *)tselemp->id; 00313 if(set) { 00314 if(sbuts) { 00315 //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c 00316 // XXX sbuts->texfrom= 0; 00317 } 00318 // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture 00319 ma->texact= (char)te->index; 00320 00321 /* also set active material */ 00322 ob->actcol= tep->index+1; 00323 } 00324 else if(tep->flag & TE_ACTIVE) { // this is active material 00325 if(ma->texact==te->index) return 1; 00326 } 00327 } 00328 00329 if(set) 00330 WM_event_add_notifier(C, NC_TEXTURE, NULL); 00331 00332 return 0; 00333 } 00334 00335 00336 static int tree_element_active_lamp(bContext *UNUSED(C), Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00337 { 00338 Object *ob; 00339 00340 /* we search for the object parent */ 00341 ob= (Object *)outliner_search_back(soops, te, ID_OB); 00342 if(ob==NULL || ob!=OBACT) return 0; // just paranoia 00343 00344 if(set) { 00345 // XXX extern_set_butspace(F5KEY, 0); 00346 } 00347 else return 1; 00348 00349 return 0; 00350 } 00351 00352 static int tree_element_active_camera(bContext *UNUSED(C), Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00353 { 00354 Object *ob= (Object *)outliner_search_back(soops, te, ID_OB); 00355 00356 if(set) 00357 return 0; 00358 00359 return scene->camera == ob; 00360 } 00361 00362 static int tree_element_active_world(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00363 { 00364 TreeElement *tep; 00365 TreeStoreElem *tselem=NULL; 00366 Scene *sce=NULL; 00367 00368 tep= te->parent; 00369 if(tep) { 00370 tselem= TREESTORE(tep); 00371 sce= (Scene *)tselem->id; 00372 } 00373 00374 if(set) { // make new scene active 00375 if(sce && scene != sce) { 00376 ED_screen_set_scene(C, sce); 00377 } 00378 } 00379 00380 if(tep==NULL || tselem->id == (ID *)scene) { 00381 if(set) { 00382 // XXX extern_set_butspace(F8KEY, 0); 00383 } 00384 else { 00385 return 1; 00386 } 00387 } 00388 return 0; 00389 } 00390 00391 static int tree_element_active_defgroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) 00392 { 00393 Object *ob; 00394 00395 /* id in tselem is object */ 00396 ob= (Object *)tselem->id; 00397 if(set) { 00398 ob->actdef= te->index+1; 00399 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00400 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); 00401 } 00402 else { 00403 if(ob==OBACT) 00404 if(ob->actdef== te->index+1) return 1; 00405 } 00406 return 0; 00407 } 00408 00409 static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) 00410 { 00411 Object *ob= (Object *)tselem->id; 00412 00413 if(set) { 00414 if (ob->pose) { 00415 ob->pose->active_group= te->index+1; 00416 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 00417 } 00418 } 00419 else { 00420 if(ob==OBACT && ob->pose) { 00421 if (ob->pose->active_group== te->index+1) return 1; 00422 } 00423 } 00424 return 0; 00425 } 00426 00427 static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) 00428 { 00429 Object *ob= (Object *)tselem->id; 00430 bArmature *arm= ob->data; 00431 bPoseChannel *pchan= te->directdata; 00432 00433 if(set) { 00434 if(!(pchan->bone->flag & BONE_HIDDEN_P)) { 00435 00436 if(set==2) ED_pose_deselectall(ob, 2); // 2 = clear active tag 00437 else ED_pose_deselectall(ob, 0); // 0 = deselect 00438 00439 if(set==2 && (pchan->bone->flag & BONE_SELECTED)) { 00440 pchan->bone->flag &= ~BONE_SELECTED; 00441 } else { 00442 pchan->bone->flag |= BONE_SELECTED; 00443 arm->act_bone= pchan->bone; 00444 } 00445 00446 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, ob); 00447 00448 } 00449 } 00450 else { 00451 if(ob==OBACT && ob->pose) { 00452 if (pchan->bone->flag & BONE_SELECTED) return 1; 00453 } 00454 } 00455 return 0; 00456 } 00457 00458 static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) 00459 { 00460 bArmature *arm= (bArmature *)tselem->id; 00461 Bone *bone= te->directdata; 00462 00463 if(set) { 00464 if(!(bone->flag & BONE_HIDDEN_P)) { 00465 if(set==2) ED_pose_deselectall(OBACT, 2); // 2 is clear active tag 00466 else ED_pose_deselectall(OBACT, 0); 00467 00468 if(set==2 && (bone->flag & BONE_SELECTED)) { 00469 bone->flag &= ~BONE_SELECTED; 00470 } else { 00471 bone->flag |= BONE_SELECTED; 00472 arm->act_bone= bone; 00473 } 00474 00475 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, OBACT); 00476 } 00477 } 00478 else { 00479 Object *ob= OBACT; 00480 00481 if(ob && ob->data==arm) { 00482 if (bone->flag & BONE_SELECTED) return 1; 00483 } 00484 } 00485 return 0; 00486 } 00487 00488 00489 /* ebones only draw in editmode armature */ 00490 static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature *arm, EditBone *ebone, short sel) 00491 { 00492 if(sel) { 00493 ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL; 00494 arm->act_edbone= ebone; 00495 // flush to parent? 00496 if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL; 00497 } 00498 else { 00499 ebone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); 00500 // flush to parent? 00501 if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag &= ~BONE_TIPSEL; 00502 } 00503 00504 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, scene->obedit); 00505 } 00506 static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) 00507 { 00508 bArmature *arm= scene->obedit->data; 00509 EditBone *ebone= te->directdata; 00510 00511 if(set==1) { 00512 if(!(ebone->flag & BONE_HIDDEN_A)) { 00513 ED_armature_deselect_all(scene->obedit, 0); // deselect 00514 tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); 00515 return 1; 00516 } 00517 } 00518 else if (set==2) { 00519 if(!(ebone->flag & BONE_HIDDEN_A)) { 00520 if(!(ebone->flag & BONE_SELECTED)) { 00521 tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); 00522 return 1; 00523 } 00524 else { 00525 /* entirely selected, so de-select */ 00526 tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE); 00527 return 0; 00528 } 00529 } 00530 } 00531 else if (ebone->flag & BONE_SELECTED) { 00532 return 1; 00533 } 00534 return 0; 00535 } 00536 00537 static int tree_element_active_modifier(bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, int set) 00538 { 00539 if(set) { 00540 Object *ob= (Object *)tselem->id; 00541 00542 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); 00543 00544 // XXX extern_set_butspace(F9KEY, 0); 00545 } 00546 00547 return 0; 00548 } 00549 00550 static int tree_element_active_psys(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *tselem, int set) 00551 { 00552 if(set) { 00553 Object *ob= (Object *)tselem->id; 00554 00555 WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); 00556 00557 // XXX extern_set_butspace(F7KEY, 0); 00558 } 00559 00560 return 0; 00561 } 00562 00563 static int tree_element_active_constraint(bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, int set) 00564 { 00565 if(set) { 00566 Object *ob= (Object *)tselem->id; 00567 00568 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00569 // XXX extern_set_butspace(F7KEY, 0); 00570 } 00571 00572 return 0; 00573 } 00574 00575 static int tree_element_active_text(bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops), TreeElement *UNUSED(te), int UNUSED(set)) 00576 { 00577 // XXX removed 00578 return 0; 00579 } 00580 00581 static int tree_element_active_pose(bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, int set) 00582 { 00583 Object *ob= (Object *)tselem->id; 00584 Base *base= object_in_scene(ob, scene); 00585 00586 if(set) { 00587 if(scene->obedit) 00588 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO); 00589 00590 if(ob->mode & OB_MODE_POSE) 00591 ED_armature_exit_posemode(C, base); 00592 else 00593 ED_armature_enter_posemode(C, base); 00594 } 00595 else { 00596 if(ob->mode & OB_MODE_POSE) return 1; 00597 } 00598 return 0; 00599 } 00600 00601 static int tree_element_active_sequence(TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) 00602 { 00603 Sequence *seq= (Sequence*) te->directdata; 00604 00605 if(set) { 00606 // XXX select_single_seq(seq, 1); 00607 } 00608 else { 00609 if(seq->flag & SELECT) 00610 return(1); 00611 } 00612 return(0); 00613 } 00614 00615 static int tree_element_active_sequence_dup(Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) 00616 { 00617 Sequence *seq, *p; 00618 Editing *ed= seq_give_editing(scene, FALSE); 00619 00620 seq= (Sequence*)te->directdata; 00621 if(set==0) { 00622 if(seq->flag & SELECT) 00623 return(1); 00624 return(0); 00625 } 00626 00627 // XXX select_single_seq(seq, 1); 00628 p= ed->seqbasep->first; 00629 while(p) { 00630 if((!p->strip) || (!p->strip->stripdata) || (!p->strip->stripdata->name)) { 00631 p= p->next; 00632 continue; 00633 } 00634 00635 // if(!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name)) 00636 // XXX select_single_seq(p, 0); 00637 p= p->next; 00638 } 00639 return(0); 00640 } 00641 00642 static int tree_element_active_keymap_item(bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) 00643 { 00644 wmKeyMapItem *kmi= te->directdata; 00645 00646 if(set==0) { 00647 if(kmi->flag & KMI_INACTIVE) return 0; 00648 return 1; 00649 } 00650 else { 00651 kmi->flag ^= KMI_INACTIVE; 00652 } 00653 return 0; 00654 } 00655 00656 /* ---------------------------------------------- */ 00657 00658 /* generic call for ID data check or make/check active in UI */ 00659 int tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) 00660 { 00661 00662 switch(te->idcode) { 00663 case ID_OB: 00664 return tree_element_set_active_object(C, scene, soops, te, set); 00665 case ID_MA: 00666 return tree_element_active_material(C, scene, soops, te, set); 00667 case ID_WO: 00668 return tree_element_active_world(C, scene, soops, te, set); 00669 case ID_LA: 00670 return tree_element_active_lamp(C, scene, soops, te, set); 00671 case ID_TE: 00672 return tree_element_active_texture(C, scene, soops, te, set); 00673 case ID_TXT: 00674 return tree_element_active_text(C, scene, soops, te, set); 00675 case ID_CA: 00676 return tree_element_active_camera(C, scene, soops, te, set); 00677 } 00678 return 0; 00679 } 00680 00681 /* generic call for non-id data to make/check active in UI */ 00682 /* Context can be NULL when set==0 */ 00683 int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set) 00684 { 00685 switch(tselem->type) { 00686 case TSE_DEFGROUP: 00687 return tree_element_active_defgroup(C, scene, te, tselem, set); 00688 case TSE_BONE: 00689 return tree_element_active_bone(C, scene, te, tselem, set); 00690 case TSE_EBONE: 00691 return tree_element_active_ebone(C, scene, te, tselem, set); 00692 case TSE_MODIFIER: 00693 return tree_element_active_modifier(C, te, tselem, set); 00694 case TSE_LINKED_OB: 00695 if(set) tree_element_set_active_object(C, scene, soops, te, set); 00696 else if(tselem->id==(ID *)OBACT) return 1; 00697 break; 00698 case TSE_LINKED_PSYS: 00699 return tree_element_active_psys(C, scene, te, tselem, set); 00700 case TSE_POSE_BASE: 00701 return tree_element_active_pose(C, scene, te, tselem, set); 00702 case TSE_POSE_CHANNEL: 00703 return tree_element_active_posechannel(C, scene, te, tselem, set); 00704 case TSE_CONSTRAINT: 00705 return tree_element_active_constraint(C, te, tselem, set); 00706 case TSE_R_LAYER: 00707 return tree_element_active_renderlayer(C, te, tselem, set); 00708 case TSE_POSEGRP: 00709 return tree_element_active_posegroup(C, scene, te, tselem, set); 00710 case TSE_SEQUENCE: 00711 return tree_element_active_sequence(te, tselem, set); 00712 case TSE_SEQUENCE_DUP: 00713 return tree_element_active_sequence_dup(scene, te, tselem, set); 00714 case TSE_KEYMAP_ITEM: 00715 return tree_element_active_keymap_item(C, te, tselem, set); 00716 00717 } 00718 return 0; 00719 } 00720 00721 /* ================================================ */ 00722 00723 static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, const float mval[2]) 00724 { 00725 00726 if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { 00727 TreeStoreElem *tselem= TREESTORE(te); 00728 int openclose= 0; 00729 00730 /* open close icon */ 00731 if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close 00732 if( mval[0]>te->xs && mval[0]<te->xs+UI_UNIT_X) 00733 openclose= 1; 00734 } 00735 00736 if(openclose) { 00737 /* all below close/open? */ 00738 if(extend) { 00739 tselem->flag &= ~TSE_CLOSED; 00740 outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1)); 00741 } 00742 else { 00743 if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED; 00744 else tselem->flag |= TSE_CLOSED; 00745 00746 } 00747 00748 return 1; 00749 } 00750 /* name and first icon */ 00751 else if(mval[0]>te->xs+UI_UNIT_X && mval[0]<te->xend) { 00752 00753 /* always makes active object */ 00754 if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP) 00755 tree_element_set_active_object(C, scene, soops, te, 1 + (extend!=0 && tselem->type==0)); 00756 00757 if(tselem->type==0) { // the lib blocks 00758 /* editmode? */ 00759 if(te->idcode==ID_SCE) { 00760 if(scene!=(Scene *)tselem->id) { 00761 ED_screen_set_scene(C, (Scene *)tselem->id); 00762 } 00763 } 00764 else if(te->idcode==ID_GR) { 00765 Group *gr= (Group *)tselem->id; 00766 GroupObject *gob; 00767 00768 if(extend) { 00769 int sel= BA_SELECT; 00770 for(gob= gr->gobject.first; gob; gob= gob->next) { 00771 if(gob->ob->flag & SELECT) { 00772 sel= BA_DESELECT; 00773 break; 00774 } 00775 } 00776 00777 for(gob= gr->gobject.first; gob; gob= gob->next) { 00778 ED_base_object_select(object_in_scene(gob->ob, scene), sel); 00779 } 00780 } 00781 else { 00782 scene_deselect_all(scene); 00783 00784 for(gob= gr->gobject.first; gob; gob= gob->next) { 00785 if((gob->ob->flag & SELECT) == 0) 00786 ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT); 00787 } 00788 } 00789 00790 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); 00791 } 00792 else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { 00793 WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); 00794 } else { // rest of types 00795 tree_element_active(C, scene, soops, te, 1); 00796 } 00797 00798 } 00799 else tree_element_type_active(C, scene, soops, te, tselem, 1+(extend!=0)); 00800 00801 return 1; 00802 } 00803 } 00804 00805 for(te= te->subtree.first; te; te= te->next) { 00806 if(do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1; 00807 } 00808 return 0; 00809 } 00810 00811 /* event can enterkey, then it opens/closes */ 00812 static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) 00813 { 00814 Scene *scene= CTX_data_scene(C); 00815 ARegion *ar= CTX_wm_region(C); 00816 SpaceOops *soops= CTX_wm_space_outliner(C); 00817 TreeElement *te; 00818 float fmval[2]; 00819 int extend= RNA_boolean_get(op->ptr, "extend"); 00820 00821 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval+1); 00822 00823 if(!ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP) && !(soops->flag & SO_HIDE_RESTRICTCOLS) && fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX) 00824 return OPERATOR_CANCELLED; 00825 00826 for(te= soops->tree.first; te; te= te->next) { 00827 if(do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break; 00828 } 00829 00830 if(te) { 00831 ED_undo_push(C, "Outliner click event"); 00832 } 00833 else { 00834 short selecting= -1; 00835 int row; 00836 00837 /* get row number - 100 here is just a dummy value since we don't need the column */ 00838 UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET, 00839 fmval[0], fmval[1], NULL, &row); 00840 00841 /* select relevant row */ 00842 outliner_select(soops, &soops->tree, &row, &selecting); 00843 00844 soops->storeflag |= SO_TREESTORE_REDRAW; 00845 00846 ED_undo_push(C, "Outliner selection event"); 00847 } 00848 00849 ED_region_tag_redraw(ar); 00850 00851 return OPERATOR_FINISHED; 00852 } 00853 00854 void OUTLINER_OT_item_activate(wmOperatorType *ot) 00855 { 00856 ot->name= "Activate Item"; 00857 ot->idname= "OUTLINER_OT_item_activate"; 00858 ot->description= "Handle mouse clicks to activate/select items"; 00859 00860 ot->invoke= outliner_item_activate; 00861 00862 ot->poll= ED_operator_outliner_active; 00863 00864 RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection for activation."); 00865 } 00866 00867 /* ****************************************************** */