Library manegement features:
authorTon Roosendaal <ton@blender.org>
Fri, 1 Dec 2006 10:12:41 +0000 (10:12 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 1 Dec 2006 10:12:41 +0000 (10:12 +0000)
- Outliner now shows hierarchy for Libraries, indicating which Library
  files invoked loading another.
- SHIFT+F1 "Append" browser has a Library menu, allowing to directly browse
  into all open library files. This will prevent accidents like re-opening
  a same .blend via another path.

source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_ID.h
source/blender/src/filesel.c
source/blender/src/header_filesel.c
source/blender/src/outliner.c

index 35613713855a8a1c8dec9fffb91473e16aa24247..fc0a756308490ed5b0a802c8697587120ae8b0e2 100644 (file)
@@ -403,8 +403,10 @@ static void add_main_to_main(Main *mainvar, Main *from)
 
 void blo_join_main(ListBase *mainlist)
 {
-       Main *tojoin, *mainl= mainlist->first;
-
+       Main *tojoin, *mainl;
+       
+       
+       mainl= mainlist->first;
        while ((tojoin= mainl->next)) {
                add_main_to_main(mainl, tojoin);
                BLI_remlink(mainlist, tojoin);
@@ -3731,99 +3733,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
        }
 }
 
-/* ********** READ LIBRARY: facility to build a tree to see dependencies *************** */
-
-typedef struct LibLink {
-       struct LibLink *prev, *next;
-       Main *lib;
-       ListBase tree;
-} LibLink;
-
-static int library_add_dependency(LibLink *llink, Main *from, Main *to)
-{
-       LibLink *lc;
-       
-       if(llink->lib==from) {
-               for(lc= llink->tree.first; lc; lc= lc->next)
-                       if(lc->lib==to)
-                               break;
-               if(lc)
-                       return;
-               
-               lc= MEM_callocN(sizeof(LibLink), "lib link");
-               BLI_addtail(&llink->tree, lc);
-               lc->lib= to;
-               
-               if(from && from->curlib) printf("Added from %s to %s \n", from->curlib->name, to->curlib->name);
-               else printf("Added to %s\n", to->curlib->name);
-               
-               return 1;
-       }
-       else {
-               for(lc= llink->tree.first; lc; lc= lc->next)
-                       if(library_add_dependency(lc, from, to))
-                               return 1;
-       }
-       if(from) printf("not added from %s to %s \n", from->curlib->name, to->curlib->name);
-       else printf("not added to %s\n", to->curlib->name);
-       return 0;
-}
-
-static void library_print_dependency(LibLink *llink, int level)
-{
-       LibLink *lc;
-       
-       for(lc= llink->tree.first; lc; lc= lc->next) {
-               int a;
-               for(a=0; a<level; a++)
-                       printf(" ");
-               printf("%s\n", lc->lib->curlib->name);
-               library_print_dependency(lc, level+1);
-       }
-}
-
-static void library_free_dependency(LibLink *llink, int level)
-{
-       LibLink *lc, *next;
-       
-       for(lc= llink->tree.first; lc; lc= next) {
-               next= lc->next;
-               library_free_dependency(lc, 1);
-       }
-       if(level)
-               MEM_freeN(llink);
-}
-
-
-static void library_do_dependency(char mode, Main *from, Main *to)
-{
-       static int doit= 0;
-       static LibLink llink;
-       
-       return;         // temporary disabled
-       
-       if(mode=='s') { /* start */
-          memset(&llink, 0, sizeof(LibLink));
-          llink.lib= from;
-          doit= 1;
-          return;
-       }
-
-       if(doit==0) return;
-
-       if(mode=='e') { /* end */
-          library_print_dependency(&llink, 1);
-          library_free_dependency(&llink, 0);
-          doit= 0;
-          return;
-       }
-       if(mode=='a') {
-               library_add_dependency(&llink, from, to);
-       }
-}
-
-
-
 /* ********** READ LIBRARY *************** */
 
 
@@ -3858,8 +3767,8 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
        newmain= MEM_callocN(sizeof(Main), "directlink");
        BLI_addtail(&fd->mainlist, newmain);
        newmain->curlib= lib;
-       
-       library_do_dependency('a', main, newmain);
+
+       lib->parent= NULL;
 }
 
 static void lib_link_library(FileData *fd, Main *main)
@@ -6322,9 +6231,6 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
        BLI_addtail(&fd->mainlist, bfd->main);
 
        bfd->main->versionfile= fd->fileversion;
-
-       /* facility to print depsgraph */
-       library_do_dependency('s', bfd->main, NULL);
        
        while(bhead) {
                switch(bhead->code) {
@@ -6366,6 +6272,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
                do_versions(fd, NULL, bfd->main);
        
        read_libraries(fd, &fd->mainlist);
+       
        blo_join_main(&fd->mainlist);
 
        lib_link_all(fd, bfd->main);
@@ -6375,9 +6282,6 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
 
        /* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
        MEM_freeN(fg);
-
-       /* facility to print depsgraph */
-       library_do_dependency('e', NULL, NULL);
        
        return bfd;
 }
@@ -6439,7 +6343,9 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                        if(bheadlib) {
                                // BHEAD+DATA dependancy
                                Library *lib= (Library *)(bheadlib+1);
-                               /* we read the lib->name directly from the bhead, potential danger (64 bits?) */
+                               /* ***************************** */
+                               /* we read the lib->name directly from the bhead, no DNA, potential danger (64 bits?) */
+                               /* ***************************** */
                                Main *main= blo_find_main(&fd->mainlist, lib->name, fd->filename);
 
                                id= is_yet_read(main, bhead);
@@ -6449,7 +6355,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                                        if(G.f & G_DEBUG) printf("expand_doit: other lib %s\n", lib->name);
                                        
                                        /* for outliner dependency only */
-                                       library_do_dependency('a', mainvar, main);
+                                       main->curlib->parent= mainvar->curlib;
                                }
                                else {
                                        //oldnewmap_insert(fd->libmap, bhead->old, id, 1);
index 638a225bd21665671d7f93a07a98ba675f639c07..080d2861a19ec87eab60ad7310c4d0ccb082927d 100644 (file)
@@ -117,14 +117,16 @@ typedef struct ID {
 
 /**
  * For each library file used, a Library struct is added to Main
+ * WARNING: readfile.c, expand_doit() reads this struct without DNA check!
  */
 typedef struct Library {
        ID id;
        ID *idblock;
        struct FileData *filedata;
-       char name[240];         /* reveiled in the UI, can store relative path */
-       char filename[240];     /* expanded name, not relative, used while reading */
-       int tot, pad;           /* tot, idblock and filedata are only fo read and write */
+       char name[240];                 /* reveiled in the UI, can store relative path */
+       char filename[240];             /* expanded name, not relative, used while reading */
+       int tot, pad;                   /* tot, idblock and filedata are only fo read and write */
+       struct Library *parent; /* for outliner, showing dependency */
 } Library;
 
 /**
index 00de9de21b3753cc9ad60514d8343b68e56cae03..815c9f8ebbd0ad6ac91a0c0b74866ccb74287514 100644 (file)
@@ -139,6 +139,16 @@ int fnmatch(const char *pattern, const char *string, int flags)
 
 #define STARTSWITH(x, y) (strncmp(x, y, sizeof(x) - 1) == 0)
 
+/* button events */
+#define B_FS_FILENAME  1
+#define B_FS_DIRNAME   2
+#define B_FS_DIR_MENU  3
+#define B_FS_PARDIR    4
+#define B_FS_LOAD      5
+#define B_FS_CANCEL    6
+#define B_FS_LIBNAME   7
+
+
 static int is_a_library(SpaceFile *sfile, char *dir, char *group);
 static void do_library_append(SpaceFile *sfile);
 static void library_to_filelist(SpaceFile *sfile);
@@ -148,7 +158,7 @@ static int groupname_to_code(char *group);
 
 extern void countall(void);
 
-/* local globals */
+/* very bad local globals */
 
 static rcti scrollrct, textrct, bar;
 static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0;
@@ -1118,6 +1128,21 @@ static void draw_filetext(SpaceFile *sfile)
        uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
 }
 
+static char *library_string(void)
+{
+       Library *lib;
+       char *str;
+       int nr=0, tot= BLI_countlist(&G.main->library);
+       
+       if(tot==0) return NULL;
+       str= MEM_callocN(tot*(FILE_MAXDIR+FILE_MAXFILE), "filesel lib menu");
+       
+       for(tot=0, lib= G.main->library.first; lib; lib= lib->id.next, nr++) {
+               tot+= sprintf(str+tot, "%s %%x%d|", lib->name+2, nr);
+       }
+       return str;
+}
+
 void drawfilespace(ScrArea *sa, void *spacedata)
 {
        SpaceFile *sfile;
@@ -1126,7 +1151,7 @@ void drawfilespace(ScrArea *sa, void *spacedata)
        int act, loadbutton;
        short mval[2];
        char name[20];
-       char *menu;
+       char *menu, *strp= NULL;
 
        myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
 
@@ -1148,6 +1173,10 @@ void drawfilespace(ScrArea *sa, void *spacedata)
        }
        else calc_file_rcts(sfile);
 
+       /* check if we load library, extra button */
+       if(sfile->type==FILE_LOADLIB)
+               strp= library_string();
+       
        /* HEADER */
        sprintf(name, "win %d", sa->win);
        block= uiNewBlock(&sa->uiblocks, name, UI_EMBOSS, UI_HELV, sa->win);
@@ -1162,28 +1191,33 @@ void drawfilespace(ScrArea *sa, void *spacedata)
        else loadbutton= 0;
 
        uiBlockBeginAlign(block);
-       uiDefBut(block, TEX,2,"",       textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "Directory, enter a directory and press enter to create it"); /* Directory input */
+       uiDefBut(block, TEX, B_FS_DIRNAME,"",   textrct.xmin + (strp?20:0), filebuty2, textrct.xmax-textrct.xmin-loadbutton - (strp?20:0), 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "Directory, enter a directory and press enter to create it"); /* Directory input */
        if(loadbutton) {
                uiSetCurFont(block, UI_HELV);
-               uiDefBut(block, BUT,        5, sfile->title,    textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+               uiDefBut(block, BUT, B_FS_LOAD, sfile->title,   textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
        }
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
-       uiDefBut(block, TEX,1,"",       textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "File, increment version number with (+/-)"); /* File input */
+       uiDefBut(block, TEX, B_FS_FILENAME,"",  textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "File, increment version number with (+/-)"); /* File input */
        if(loadbutton) {
                uiSetCurFont(block, UI_HELV);
-               uiDefBut(block, BUT,        6, "Cancel",        textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+               uiDefBut(block, BUT, B_FS_CANCEL, "Cancel",     textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
        }
        uiBlockEndAlign(block);
        
        menu= fsmenu_build_menu();
-       if(menu[0])     // happens when no .Bfs is there, and first time browse
-               uiDefButS(block, MENU,  3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
+       if(menu[0])     /* happens when no .Bfs is there, and first time browse */
+               uiDefButS(block, MENU, B_FS_DIR_MENU, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
        MEM_freeN(menu);
 
-       uiDefBut(block, BUT,            4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
-
+       uiBlockBeginAlign(block);
+       uiDefBut(block, BUT, B_FS_PARDIR, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
+       if(strp) {
+               uiDefIconTextButS(block, MENU, B_FS_LIBNAME, ICON_LIBRARY_DEHLT, strp, scrollrct.xmin+20, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
+               MEM_freeN(strp);
+       }
+                        
        uiDrawBlock(block);
 
        draw_filescroll(sfile);
@@ -1587,7 +1621,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile)
 {
        char butname[FILE_MAXDIR+FILE_MAXFILE];
        
-       if (event == 1) {
+       if (event == B_FS_FILENAME) {
                if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
                        int i, match = FALSE;
                        
@@ -1602,7 +1636,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile)
                        scrarea_queue_winredraw(curarea);
                }
        }
-       else if(event== 2) {
+       else if(event== B_FS_DIRNAME) {
                /* reuse the butname variable */
                BLI_cleanup_dir(G.sce, sfile->dir);
 
@@ -1625,7 +1659,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile)
                sfile->ofs= 0;
                scrarea_queue_winredraw(curarea);
        }
-       else if(event== 3) {
+       else if(event== B_FS_DIR_MENU) {
                char *selected= fsmenu_get_entry(sfile->menu-1);
                
                /* which string */
@@ -1641,11 +1675,26 @@ static void do_filesel_buttons(short event, SpaceFile *sfile)
                sfile->act= -1;
                
        }
-       else if(event== 4) parent(sfile);
-       else if(event== 5) {
-               if(sfile->type) filesel_execute(sfile);
+       else if(event== B_FS_PARDIR) 
+               parent(sfile);
+       else if(event== B_FS_LOAD) {
+               if(sfile->type) 
+                       filesel_execute(sfile);
+       }
+       else if(event== B_FS_CANCEL) 
+               filesel_prevspace();
+       else if(event== B_FS_LIBNAME) {
+               Library *lib= BLI_findlink(&G.main->library, sfile->menu);
+               if(lib) {
+                       BLI_strncpy(sfile->dir, lib->filename, sizeof(sfile->dir));
+                       BLI_make_exist(sfile->dir);
+                       BLI_cleanup_dir(G.sce, sfile->dir);
+                       freefilelist(sfile);
+                       sfile->ofs= 0;
+                       scrarea_queue_winredraw(curarea);
+                       sfile->act= -1;
+               }
        }
-       else if(event== 6) filesel_prevspace();
        
 }
 
@@ -2244,73 +2293,6 @@ static int is_a_library(SpaceFile *sfile, char *dir, char *group)
        return 1;
 }
 
-/* orange hack... :) */
-static void do_sync_pose(Library *lib)
-{
-       Object *ob, *obt;
-       Base *base;
-       bArmature *arm;
-       
-       /* find the armature and the pose from library */
-       for(ob= G.main->object.first; ob; ob= ob->id.next)
-               if(ob->type==OB_ARMATURE && ob->id.lib==lib)
-                       break;
-       
-       if(ob==NULL || ob->pose==NULL) {
-               error("No pose appended");
-               return;
-       }
-       
-       arm= ob->data;
-
-       /* for all visible objects in this scene */
-       for(base= G.scene->base.first; base; base= base->next) {
-               if((base->flag & SELECT)) {
-                       obt= base->object;
-                       if(obt->type==OB_ARMATURE && obt->pose && ob!=obt) {
-                               char str[128];
-                               
-                               sprintf(str, "Replace Object %s", obt->id.name);
-                               if(okee(str)) {
-                                       bPoseChannel *chan;
-                                       bArmature *oldarm= obt->data;
-                                       
-                                       /* link armature */
-                                       oldarm->id.us--;
-                                       obt->data= arm;
-                                       arm->id.us++;
-                                       
-                                       /* link pose */
-                                       free_pose_channels(obt->pose);
-                                       MEM_freeN(obt->pose);
-                                       copy_pose(&obt->pose, ob->pose, 1);
-                                       
-                                       /* relink */
-                                       ob->id.newid= &obt->id;
-                                       for (chan = obt->pose->chanbase.first; chan; chan=chan->next){
-                                               relink_constraints(&chan->constraints);
-                                       }
-                                       
-                                       obt->pose->flag |= POSE_RECALC;
-                                       obt->recalc |= OB_RECALC_DATA;
-                               }
-                       }
-               }
-       }
-
-       /* prevent saving in file, unlink from scene */
-       for(base= G.scene->base.first; base; base= base->next) {
-               if(base->object==ob)
-                       break;
-       }
-       
-       if(base) {
-               free_and_unlink_base(base);
-       }
-
-       DAG_scene_sort(G.scene);        // for accidentally appended other objects
-}
-
 static void do_library_append(SpaceFile *sfile)
 {
        Library *lib;
@@ -2347,8 +2329,6 @@ static void do_library_append(SpaceFile *sfile)
                }
                
                if(lib) {
-                       if(sfile->flag & FILE_SYNCPOSE)
-                               do_sync_pose(lib);
                        if((sfile->flag & FILE_LINK)==0) 
                                all_local(lib);
                }
index 74886c8495c05d3e4fe2902ecc41a3225b73d423..4e7c94e718169805dde061fa23c0963fc1a01181 100644 (file)
@@ -145,7 +145,6 @@ void file_buttons(void)
                uiDefButBitS(block, TOG, FILE_AUTOSELECT, B_REDR, "Autosel", xco+=125,0,65,YIC, &sfile->flag, 0, 0, 0, 0, "Autoselect imported objects");
                uiDefButBitS(block, TOG, FILE_ACTIVELAY, B_REDR, "Active Layer", xco+=65,0,80,YIC, &sfile->flag, 0, 0, 0, 0, "Append object(s) in active layer");
                uiDefButBitS(block, TOG, FILE_ATCURSOR, B_REDR, "At Cursor", xco+=80,0,65,YIC, &sfile->flag, 0, 0, 0, 0, "Append object(s) at cursor, use centroid if more than one object is selected");
-               uiDefButBitS(block, TOG, FILE_SYNCPOSE, B_REDR, "Sync Pose", xco+=80,0,65,YIC, &sfile->flag, 0, 0, 0, 0, "If Object with Pose appended, link the Pose and Armature to all selected Objects");
                uiBlockEndAlign(block);
                
                xco+= 100;      // scroll
index 18ef168b7e6a0d9578fd40ca8208eebc227ae78b..565a4998c0ed847024420f3cc8e8bbedaea68e69 100644 (file)
@@ -842,9 +842,29 @@ static void outliner_build_tree(SpaceOops *soops)
        /* options */
        if(soops->outlinevis == SO_LIBRARIES) {
                Library *lib;
+               
                for(lib= G.main->library.first; lib; lib= lib->id.next) {
-                       outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
-               }
+                       ten= outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
+                       lib->id.newid= (ID *)ten;
+               }
+               /* make hierarchy */
+               ten= soops->tree.first;
+               while(ten) {
+                       TreeElement *nten= ten->next, *par;
+                       tselem= TREESTORE(ten);
+                       lib= (Library *)tselem->id;
+                       if(lib->parent) {
+                               BLI_remlink(&soops->tree, ten);
+                               par= (TreeElement *)lib->parent->id.newid;
+                               BLI_addtail(&par->subtree, ten);
+                               ten->parent= par;
+                       }
+                       ten= nten;
+               }
+               /* restore newid pointers */
+               for(lib= G.main->library.first; lib; lib= lib->id.next)
+                       lib->id.newid= NULL;
+               
        }
        else if(soops->outlinevis == SO_ALL_SCENES) {
                Scene *sce;
@@ -1637,9 +1657,9 @@ static int tree_element_type_active(SpaceOops *soops, TreeElement *te, TreeStore
        return 0;
 }
 
+#ifdef WITH_VERSE
 static void verse_operation_menu(TreeElement *te)
 {
-#ifdef WITH_VERSE
        short event=0;
        if(te->idcode==ID_VS) {
                struct VerseSession *session = (VerseSession*)te->directdata;
@@ -1713,9 +1733,8 @@ static void verse_operation_menu(TreeElement *te)
                                break;
                }
        }
-#endif
-
 }
+#endif
 
 
 static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short event, float *mval)
@@ -2711,7 +2730,7 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
                        case ID_GR:
                                BIF_icon_draw(x, y, ICON_CIRCLE_DEHLT); break;
                        case ID_LI:
-                               BIF_icon_draw(x, y, ICON_PARLIB); break;
+                               BIF_icon_draw(x, y, ICON_LIBRARY_DEHLT); break;
                }
        }
 }