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