Another merger of Orange branch with bf-blender, it has important fixes.
authorTon Roosendaal <ton@blender.org>
Wed, 14 Dec 2005 20:38:14 +0000 (20:38 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 14 Dec 2005 20:38:14 +0000 (20:38 +0000)
1  2 
source/blender/blenloader/intern/readfile.c
source/blender/src/editnla.c
source/blender/src/header_view3d.c

index e2528e349f04693a4362322b284398af315994ba,cb4e7546b53cfeb497311aff24d2b5f9606fbf0a..5dfde4843a04df5f35d071c3a5728633e1b84f35
@@@ -1,12 -1,19 +1,12 @@@
  /*
 - * readfile.c
 - *
 - * .blend file reading
 - *
   * $Id$
   *
 - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 + * ***** BEGIN GPL LICENSE BLOCK *****
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
 - * of the License, or (at your option) any later version. The Blender
 - * Foundation also sells licenses for use in proprietary software under
 - * the Blender License.  See http://www.blender.org/BL/ for information
 - * about this.
 + * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@@ -24,7 -31,7 +24,7 @@@
   *
   * Contributor(s): none yet.
   *
 - * ***** END GPL/BL DUAL LICENSE BLOCK *****
 + * ***** END GPL LICENSE BLOCK *****
   *
   */
  
@@@ -237,8 -244,7 +237,8 @@@ typedef struct OldNewMap 
  extern          short freeN(void *vmemh); /* defined in util.h */  
  
  
 -static OldNewMap *oldnewmap_new(void) {
 +static OldNewMap *oldnewmap_new(void) 
 +{
        OldNewMap *onm= MEM_mallocN(sizeof(*onm), "OldNewMap");
        onm->lasthit= 0;
        onm->nentries= 0;
        return onm;
  }
  
 -static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) {
 +static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) 
 +{
        OldNew *entry;
  
        if (onm->nentries==onm->entriessize) {
        entry->nr= nr;
  }
  
 -static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) {
 +static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) 
 +{
        int i;
  
        if (onm->lasthit<onm->nentries-1) {
        return NULL;
  }
  
 -static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib) {
 +static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib) 
 +{
        int i;
 -
 +      
        if (onm->lasthit<onm->nentries-1) {
                OldNew *entry= &onm->entries[++onm->lasthit];
  
                }
        }
  
 -      for (i=0; i<onm->nentries; i++) {
 +      /* note; we go backwards over this list, to prevent a case that still needs fix;
 +         if 1 library has blocks used both direct and indirect, it has two entries in this
 +              table, and only the first entry gets remapped in change_lib_adr. */
 +      
 +      for (i=onm->nentries-1; i>=0; i--) {
                OldNew *entry= &onm->entries[i];
  
                if (entry->old==addr) {
                        if (id && (!lib || id->lib)) {
                                entry->nr++;
  
 +                              //if(retval) printf("ack double hit for %s and %s\n", id->name, ((ID *)retval)->name);
                                return entry->newp;
                        }
                }
        return NULL;
  }
  
 -static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, short type) {
 +static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, void *lib, short type) 
 +{
        int i;
  
        if (onm->lasthit<onm->nentries-1) {
                if (entry->old==addr) {
                        ID *id= entry->newp;
  
 -                      if (id && (GS(id->name) == type)) {
 +                      if (id && (GS(id->name) == type) && (!lib || id->lib)) {
                                entry->nr++;
  
                                return entry->newp;
                if (entry->old==addr) {
                        ID *id= entry->newp;
  
 -                      if (id && (GS(id->name) == type)) {
 +                      if (id && (GS(id->name) == type) && (!lib || id->lib)) {
                                entry->nr++;
  
                                return entry->newp;
        return NULL;
  }
  
 -static void oldnewmap_free_unused(OldNewMap *onm) {
 +static void oldnewmap_free_unused(OldNewMap *onm) 
 +{
        int i;
  
        for (i=0; i<onm->nentries; i++) {
        }
  }
  
 -static void oldnewmap_clear(OldNewMap *onm) {
 +static void oldnewmap_clear(OldNewMap *onm) 
 +{
        onm->nentries= 0;
        onm->lasthit= 0;
  }
  
 -static void oldnewmap_free(OldNewMap *onm) {
 +static void oldnewmap_free(OldNewMap *onm) 
 +{
        MEM_freeN(onm->entries);
        MEM_freeN(onm);
  }
@@@ -461,6 -455,7 +461,6 @@@ void blo_split_main(ListBase *mainlist
        for (lib= mainl->library.first; lib; lib= lib->id.next) {
                Main *libmain= MEM_callocN(sizeof(Main), "libmain");
                libmain->curlib= lib;
 -
                BLI_addtail(mainlist, libmain);
        }
  
                split_libdata(lbarray[i], mainl->next);
  }
  
 +static void cleanup_path(const char *relabase, char *name)
 +{
 +      char filename[FILE_MAXFILE];
 +      
 +      BLI_splitdirstring(name, filename);
 +      BLI_cleanup_dir(relabase, name);
 +      strcat(name, filename);
 +}
 +
  static Main *blo_find_main(ListBase *mainlist, char *name)
  {
        Main *m;
        Library *lib;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        char libname1[FILE_MAXDIR+FILE_MAXFILE];
 -
 -      /* name can be stringcode too */
 +      
 +//    printf("G.sce %s\n", G.sce);
 +      /* everything in absolute paths now */
 +      
        strcpy(name1, name);
 -      BLI_convertstringcode(name1, G.sce, 0);
 +      cleanup_path(G.sce, name1);
 +//    printf("original in  %s\n", name);
 +//    printf("converted in %s\n", name1);
  
        for (m= mainlist->first; m; m= m->next) {
                char *libname= (m->curlib)?m->curlib->name:m->name;
                
 +//            printf("libname %s\n", libname);
                strcpy(libname1, libname);
 -              BLI_convertstringcode(libname1, G.sce, 0);
 +              cleanup_path(G.sce, libname1);
 +//            printf("libname1 %s\n", libname1, name1);
                
 -              if (BLI_streq(name1, libname1))
 +              if (BLI_streq(name1, libname1)) {
 +                      printf("found library %s\n", libname);
                        return m;
 +              }
        }
  
        m= MEM_callocN(sizeof(Main), "find_main");
        lib= alloc_libblock(&m->library, ID_LI, "lib");
        strcpy(lib->name, name);
        m->curlib= lib;
 -
 +      
 +      printf("added new lib %s\n", name);
        return m;
  }
  
@@@ -920,19 -897,6 +920,19 @@@ FileData *blo_openblenderfile(char *nam
        gzFile gzfile;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        
 +      /* relative path rescue... */
 +      if(G.rt==111) {
 +              int len= strlen(name);
 +              printf("old %s\n", name);
 +              while(len-- > 1) {
 +                      if(name[len]=='/' && name[len-1]=='/') {
 +                              strcpy(name, name+len-1);
 +                              printf("new %s\n", name);
 +                              break;
 +                      }
 +              }
 +      }
 +      
        /* library files can have stringcodes */
        strcpy(name1, name);
        if(name[0]=='/' && name[1]=='/')
@@@ -1051,9 -1015,9 +1051,9 @@@ static void *newlibadr(FileData *fd, vo
        return oldnewmap_liblookup_and_inc(fd->libmap, adr, lib);
  }
  
 -static void *newlibadr_us_type(FileData *fd, short type, void *adr)   /* only Lib data */
 +static void *newlibadr_us_type(FileData *fd, void *lib, short type, void *adr)        /* only Lib data */
  {
 -      ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, type);
 +      ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, lib, type);
  
        if (id) {
                id->us++;
@@@ -1297,7 -1261,6 +1297,7 @@@ static void lib_link_nlastrips(FileDat
        bActionStrip *strip;
  
        for (strip=striplist->first; strip; strip=strip->next){
 +              strip->object = newlibadr(fd, id->lib, strip->object);
                strip->act = newlibadr_us(fd, id->lib, strip->act);
                strip->ipo = newlibadr(fd, id->lib, strip->ipo);
        }
@@@ -1416,6 -1379,7 +1416,7 @@@ static void lib_link_pose(FileData *fd
  {
        bPoseChannel *pchan;
        bArmature *arm= ob->data;
+       int rebuild= 0;
        if (!pose)
                return;
  
                lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
                // hurms... loop in a loop, but yah... later... (ton)
                pchan->bone= get_named_bone(arm, pchan->name);
 +              pchan->custom= newlibadr(fd, arm->id.lib, pchan->custom);
+               if(pchan->bone==NULL)
+                       rebuild= 1;
+       }
+       if(rebuild) {
+               ob->recalc= OB_RECALC;
+               pose->flag |= POSE_RECALC;
        }
  }
  
@@@ -2021,7 -1990,6 +2028,7 @@@ static void direct_link_texture(FileDat
  static void lib_link_material(FileData *fd, Main *main)
  {
        Material *ma;
 +      MaterialLayer *ml;
        MTex *mtex;
        int a;
  
                if(ma->id.flag & LIB_NEEDLINK) {
  
                        ma->ipo= newlibadr_us(fd, ma->id.lib, ma->ipo);
 +                      ma->group= newlibadr_us(fd, ma->id.lib, ma->group);
  
                        for(a=0; a<MAX_MTEX; a++) {
                                mtex= ma->mtex[a];
                                }
                        }
                        lib_link_scriptlink(fd, &ma->id, &ma->scriptlink);
 +                      
 +                      for (ml=ma->layers.first; ml; ml=ml->next)
 +                              ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat);
 +                              
                        ma->id.flag -= LIB_NEEDLINK;
                }
                ma= ma->id.next;
@@@ -2054,6 -2017,8 +2061,6 @@@ static void direct_link_material(FileDa
  {
        int a;
  
 -      direct_link_scriptlink(fd, &ma->scriptlink);
 -
        for(a=0; a<MAX_MTEX; a++) {
                ma->mtex[a]= newdataadr(fd, ma->mtex[a]);
        }
        ma->ramp_col= newdataadr(fd, ma->ramp_col);
        ma->ramp_spec= newdataadr(fd, ma->ramp_spec);
        
 +      direct_link_scriptlink(fd, &ma->scriptlink);
 +      
 +      link_list(fd, &ma->layers);
 +
  }
  
  /* ************ READ MESH ***************** */
@@@ -2175,7 -2136,6 +2182,7 @@@ static void lib_link_modifiers(FileDat
  static void lib_link_object(FileData *fd, Main *main)
  {
        Object *ob;
 +      PartEff *paf;
        bSensor *sens;
        bController *cont;
        bActuator *act;
                        ob->track= newlibadr(fd, ob->id.lib, ob->track);
                        ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
                        ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
 -
 +                      ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
 +                      
                        poin= ob->data;
                        ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
 -
 +                      
                        if(ob->data==NULL && poin!=NULL) {
                                ob->type= OB_EMPTY;
                                warn= 1;
                        lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
                        lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels);
  
 +                      for(paf= ob->effect.first; paf; paf= paf->next) {
 +                              if(paf->type==EFF_PARTICLE) {
 +                                      paf->group= newlibadr_us(fd, ob->id.lib, paf->group);
 +                              }
 +                      }                               
  
                        sens= ob->sensors.first;
                        while(sens) {
@@@ -2390,7 -2344,7 +2397,7 @@@ static void direct_link_object(FileDat
        paf= ob->effect.first;
        while(paf) {
                if(paf->type==EFF_PARTICLE) {
 -                      paf->keys= 0;
 +                      paf->keys= NULL;
                }
                if(paf->type==EFF_WAVE) {
                        WaveEff *wav = (WaveEff*) paf;
@@@ -2549,13 -2503,14 +2556,13 @@@ static void lib_link_scene(FileData *fd
                        sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
                        sce->set= newlibadr(fd, sce->id.lib, sce->set);
                        sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima);
 -                      sce->group= newlibadr_us(fd, sce->id.lib, sce->group);
  
                        base= sce->base.first;
                        while(base) {
                                next= base->next;
  
                                /* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
 -                              base->object= newlibadr_us_type(fd, ID_OB, base->object);
 +                              base->object= newlibadr_us_type(fd, sce->id.lib, ID_OB, base->object);
                                
                                /* when save during radiotool, needs cleared */
                                base->flag &= ~OB_RADIO;
@@@ -3142,25 -3097,10 +3149,25 @@@ static void direct_link_screen(FileDat
  /* ********** READ LIBRARY *************** */
  
  
 -static void direct_link_library(FileData *fd, Library *lib)
 +static void direct_link_library(FileData *fd, Library *lib, Main *main)
  {
        Main *newmain;
 -
 +      Library *libr;
 +      
 +      for(newmain= fd->mainlist.first; newmain; newmain= newmain->next) {
 +              if(newmain->curlib) {
 +                      if(strcmp(newmain->curlib->name, lib->name)==0) {
 +                              printf("Fixed error in file; multiple instances of lib:\n %s\n", lib->name);
 +                              
 +                              change_libadr(fd, lib, newmain->curlib);
 +                              
 +                              BLI_remlink(&main->library, lib);
 +                              MEM_freeN(lib);
 +                              return;
 +                      }
 +              }
 +      }
 +      
        /* new main */
        newmain= MEM_callocN(sizeof(Main), "directlink");
        BLI_addtail(&fd->mainlist, newmain);
@@@ -3207,35 -3147,47 +3214,35 @@@ static void lib_link_sound(FileData *fd
  
  static void direct_link_group(FileData *fd, Group *group)
  {
 -      GroupObject *go;
 -      ObjectKey *ok;
 -
        link_list(fd, &group->gobject);
 -      link_list(fd, &group->gkey);
 -      group->active= newdataadr(fd, group->active);
 -
 -      go= group->gobject.first;
 -      while(go) {
 -              link_list(fd, &go->okey);
 -              ok= go->okey.first;
 -              while(ok) {
 -                      ok->gkey= newdataadr(fd, ok->gkey);
 -                      ok= ok->next;
 -              }
 -              go= go->next;
 -      }
  }
  
  static void lib_link_group(FileData *fd, Main *main)
  {
        Group *group= main->group.first;
        GroupObject *go;
 -      ObjectKey *ok;
 -
 +      int add_us;
 +      
        while(group) {
                if(group->id.flag & LIB_NEEDLINK) {
                        group->id.flag -= LIB_NEEDLINK;
 -
 +                      
 +                      add_us= 0;
 +                      
                        go= group->gobject.first;
                        while(go) {
                                go->ob= newlibadr(fd, group->id.lib, go->ob);
 -                              ok= go->okey.first;
 -                              while(ok) {
 -                                      ok->parent= newlibadr(fd, group->id.lib, ok->parent);
 -                                      ok->track= newlibadr(fd, group->id.lib, ok->track);
 -                                      ok->ipo= newlibadr_us(fd, group->id.lib, ok->ipo);
 -                                      ok= ok->next;
 +                              if(go->ob) {
 +                                      /* if group has an object, it increments user... */
 +                                      add_us= 1;
 +                                      if(go->ob->id.us==0) 
 +                                              go->ob->id.us= 1;
                                }
                                go= go->next;
                        }
 +                      if(add_us) group->id.us++;
 +                      rem_from_group(group, NULL);    /* removes NULL entries */
 +                      
                }
                group= group->id.next;
        }
@@@ -3378,7 -3330,7 +3385,7 @@@ static BHead *read_libblock(FileData *f
                        direct_link_world(fd, (World *)id);
                        break;
                case ID_LI:
 -                      direct_link_library(fd, (Library *)id);
 +                      direct_link_library(fd, (Library *)id, main);
                        break;
                case ID_CA:
                        direct_link_camera(fd, (Camera *)id);
@@@ -3476,17 -3428,6 +3483,17 @@@ static void bone_version_238(ListBase *
        }
  }
  
 +static void bone_version_239(ListBase *lb)
 +{
 +      Bone *bone;
 +      
 +      for(bone= lb->first; bone; bone= bone->next) {
 +              if(bone->layer==0) 
 +                      bone->layer= 1;
 +              bone_version_239(&bone->childbase);
 +      }
 +}
 +
  static void do_versions(FileData *fd, Library *lib, Main *main)
  {
        /* WATCH IT!!!: pointers from libdata have not been converted */
                /* updating stepsize for ghost drawing */
                for(arm= main->armature.first; arm; arm= arm->id.next) {
                        if (arm->ghostsize==0) arm->ghostsize=1;
 +                      bone_version_239(&arm->bonebase);
 +                      if(arm->layer==0) arm->layer= 1;
                }
                
                for(;sce;sce= sce->id.next) {
                                if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF;
                                ma->pad= 1;
                        }
 +                      /* orange stuff, so should be done for 2.40 too */
 +                      if(ma->layers.first==NULL) {
 +                              ma->ml_flag= ML_RENDER;
 +                      }
                }
        }
        
@@@ -5330,7 -5265,6 +5337,7 @@@ static void expand_doit(FileData *fd, M
                        if(bheadlib) {
                                // BHEAD+DATA dependancy
                                Library *lib= (Library *)(bheadlib+1);
 +                              /* we read the lib->name directly from the bhead, potential danger (64 bits?) */
                                mainvar= blo_find_main(&fd->mainlist, lib->name);
  
                                id= is_yet_read(mainvar, bhead);
        }
  }
  
 +static void expand_group(FileData *fd, Main *mainvar, Group *group)
 +{
 +      GroupObject *go;
 +      
 +      for(go= group->gobject.first; go; go= go->next) {
 +              expand_doit(fd, mainvar, go->ob);
 +      }
 +}
 +
  static void expand_key(FileData *fd, Main *mainvar, Key *key)
  {
        expand_doit(fd, mainvar, key->ipo);
@@@ -5383,7 -5308,6 +5390,7 @@@ static void expand_texture(FileData *fd
  
  static void expand_material(FileData *fd, Main *mainvar, Material *ma)
  {
 +      MaterialLayer *ml;
        int a;
  
        for(a=0; a<MAX_MTEX; a++) {
                        expand_doit(fd, mainvar, ma->mtex[a]->object);
                }
        }
 +      
        expand_doit(fd, mainvar, ma->ipo);
 +      
 +      for (ml=ma->layers.first; ml; ml=ml->next) {
 +              if(ml->mat)
 +                      expand_doit(fd, mainvar, ml->mat);
 +      }
  }
  
  static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
@@@ -5644,7 -5562,6 +5651,7 @@@ static void expand_object(FileData *fd
        expand_constraint_channels(fd, mainvar, &ob->constraintChannels);
  
        for (strip=ob->nlastrips.first; strip; strip=strip->next){
 +              expand_doit(fd, mainvar, strip->object);
                expand_doit(fd, mainvar, strip->act);
                expand_doit(fd, mainvar, strip->ipo);
        }
@@@ -5808,9 -5725,6 +5815,9 @@@ static void expand_main(FileData *fd, M
                                        case ID_AC:
                                                expand_action(fd, mainvar, (bAction *)id);
                                                break;
 +                                      case ID_GR:
 +                                              expand_group(fd, mainvar, (Group *)id);
 +                                              break;
                                        }
  
                                        doit= 1;
@@@ -5840,9 -5754,8 +5847,9 @@@ static void give_base_to_objects(Scene 
                                BLI_addtail(&(sce->base), base);
                                base->lay= ob->lay;
                                base->object= ob;
 +                              base->flag= ob->flag;
                                ob->id.us= 1;
 -
 +                              
                                ob->id.flag -= LIB_INDIRECT;
                                ob->id.flag |= LIB_EXTERN;
  
@@@ -6017,8 -5930,7 +6024,8 @@@ void BLO_library_append(SpaceFile *sfil
        
        /* make copy of the 'last loaded filename', we need to restore it */
        BLI_strncpy(filename, G.sce, sizeof(filename));
 -      BLI_strncpy(G.sce, fd->filename, sizeof(filename));             // already opened file, to reconstruct relative paths
 +      
 +      BLI_strncpy(G.sce, G.main->name, sizeof(G.main->name));         // original file, to reconstruct relative paths for current append
        
        if(sfile->flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
  
        read_libraries(fd, &fd->mainlist);
  
        if(sfile->flag & FILE_STRINGCODE) {
 +
                /* uses old .blend file (*filename) as reference */
                BLI_makestringcode(filename, mainl->curlib->name);
                /* the caller checks for appended library, so we make sure names match */
index e4eafff8fd907503b3108fd794ee0fe318bdaff8,74e3bbd1d340c185bd2824d263bb447ceb22b4f9..49455f392ca3adac3f73c77d0d1ba38306601573
@@@ -1,12 -1,15 +1,12 @@@
  /**
 -* $Id$
 -*
 - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 + * $Id$
 + *
 + * ***** BEGIN GPL BLOCK *****
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
 - * of the License, or (at your option) any later version. The Blender
 - * Foundation also sells licenses for use in proprietary software under
 - * the Blender License.  See http://www.blender.org/BL/ for information
 - * about this.
 + * of the License, or (at your option) any later version. 
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   *
   * Contributor(s): none yet.
   *
 - * ***** END GPL/BL DUAL LICENSE BLOCK *****
 -* This file is a horrible mess: An attmept to cram some
 -* final functionality into blender before it is too late.
 -*
 -* Hopefully it can be tidied up at a later date...
 + * ***** END GPL *****
 + *
 + * This file is a horrible mess: An attmept to cram some
 + * final functionality into blender before it is too late.
 + *
 + * Hopefully it can be tidied up at a later date...
  */
  
  #include <stdlib.h>
  
  #include "BLI_blenlib.h"
  
 +#include "DNA_action_types.h"
 +#include "DNA_constraint_types.h"
 +#include "DNA_curve_types.h"
 +#include "DNA_ipo_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_nla_types.h"
  #include "DNA_screen_types.h"
  #include "DNA_space_types.h"
  #include "DNA_scene_types.h"
 -#include "DNA_ipo_types.h"
 -#include "DNA_curve_types.h"
 -#include "DNA_object_types.h"
  #include "DNA_userdef_types.h"
 -#include "DNA_action_types.h"
 -#include "DNA_nla_types.h"
 -#include "DNA_constraint_types.h"
  
  #include "BKE_action.h"
  #include "BKE_depsgraph.h"
 +#include "BKE_group.h"
  #include "BKE_global.h"
  #include "BKE_ipo.h"
  #include "BKE_library.h"
@@@ -96,6 -97,7 +96,6 @@@ static Base *get_nearest_nlachannel_ob_
  static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel);
  static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel);
  static void mouse_nlachannels(short mval[2]);
 -static void add_nlablock(short mval[2]);
  static void convert_nla(short mval[2]);
  
  /* ******************** SPACE: NLA ********************** */
@@@ -247,6 -249,189 +247,6 @@@ void snap_action_strips(void
        allqueue (REDRAWNLA, 0);
  }
  
 -void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 -{
 -      unsigned short event= evt->event;
 -      short val= evt->val;
 -      SpaceNla *snla = curarea->spacedata.first;
 -      int doredraw= 0;
 -      short   mval[2];
 -      float dx,dy;
 -      int     cfra;
 -      short mousebut = L_MOUSE;
 -      
 -      if (curarea->win==0) return;
 -      if (!snla) return;
 -      
 -      if(val) {
 -              if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
 -              
 -              /* swap mouse buttons based on user preference */
 -              if (U.flag & USER_LMOUSESELECT) {
 -                      if (event == LEFTMOUSE) {
 -                              event = RIGHTMOUSE;
 -                              mousebut = L_MOUSE;
 -                      } else if (event == RIGHTMOUSE) {
 -                              event = LEFTMOUSE;
 -                              mousebut = R_MOUSE;
 -                      }
 -              }
 -              
 -              getmouseco_areawin(mval);
 -              
 -              switch(event) {
 -              case UI_BUT_EVENT:
 -                      do_nlabuts(val); // in drawnla.c
 -                      break;
 -              
 -              case HOMEKEY:
 -                      do_nla_buttons(B_NLAHOME);
 -                      break;
 -
 -              case EQUALKEY:
 -              case PAGEUPKEY:
 -                      shift_nlastrips_up();
 -                      break;
 -
 -              case MINUSKEY:
 -              case PAGEDOWNKEY:
 -                      shift_nlastrips_down();
 -                      break;
 -
 -              case AKEY:
 -                      if (G.qual & LR_SHIFTKEY){
 -                              add_nlablock(mval);
 -                              allqueue (REDRAWNLA, 0);
 -                              allqueue (REDRAWVIEW3D, 0);
 -                      }
 -                      else{
 -                              if (mval[0]>=NLAWIDTH)
 -                                      deselect_nlachannel_keys(1);
 -                              else{
 -                                      deselect_nlachannels(1);
 -                                      allqueue (REDRAWVIEW3D, 0);
 -                              }
 -                              allqueue (REDRAWNLA, 0);
 -                              allqueue (REDRAWIPO, 0);
 -                              BIF_undo_push("(De)select all NLA");
 -                      }
 -                      break;
 -
 -              case BKEY:
 -                      borderselect_nla();
 -                      break;
 -
 -              case CKEY:
 -                      convert_nla(mval);
 -                      break;
 -                      
 -              case DKEY:
 -                      if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){
 -                              duplicate_nlachannel_keys();
 -                              update_for_newframe_muted();
 -                      }
 -                      break;
 -
 -              case GKEY:
 -                      if (mval[0]>=NLAWIDTH)
 -                              transform_nlachannel_keys ('g', 0);
 -                      update_for_newframe_muted();
 -                      break;
 -
 -              case NKEY:
 -                      if(G.qual==0) {
 -                              toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
 -                              scrarea_queue_winredraw(curarea);
 -                      }
 -                      break;
 -
 -              case SKEY:
 -                      if(G.qual==LR_ALTKEY) {
 -                              val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2");
 -                              if(val==1)
 -                                      reset_action_strips(1);
 -                              else if(val==2)
 -                                      reset_action_strips(2);
 -                      }
 -                      else if(G.qual & LR_SHIFTKEY) {
 -                              if(okee("Snap Strips to Frame"))
 -                                      snap_action_strips();
 -                      }
 -                      else {
 -                              if (mval[0]>=NLAWIDTH)
 -                                      transform_nlachannel_keys ('s', 0);
 -                              update_for_newframe_muted();
 -                      }
 -                      break;
 -
 -              case DELKEY:
 -              case XKEY:
 -                      if (mval[0]>=NLAWIDTH)
 -                              delete_nlachannel_keys ();
 -
 -                      update_for_newframe_muted();
 -                      break;
 -                      
 -              /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above,
 -               * based on user preference USER_LMOUSESELECT
 -               */
 -              case LEFTMOUSE:
 -                      if(view2dmove(LEFTMOUSE))
 -                              break; // only checks for sliders
 -                      else if (mval[0]>=snla->v2d.mask.xmin) {
 -                              do {
 -                                      getmouseco_areawin(mval);
 -                                      
 -                                      areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
 -                                      
 -                                      cfra= (int)dx;
 -                                      if(cfra< 1) cfra= 1;
 -                                      
 -                                      if( cfra!=CFRA ) {
 -                                              CFRA= cfra;
 -                                              update_for_newframe();
 -                                              force_draw_all(0);
 -                                      }
 -                                      else PIL_sleep_ms(30);
 -                                      
 -                              } while(get_mbut() & mousebut);
 -                              break;
 -                      }
 -                      /* else pass on! */
 -              case RIGHTMOUSE:
 -                      if (mval[0]>=snla->v2d.mask.xmin) {
 -                              if(G.qual & LR_SHIFTKEY)
 -                                      mouse_nla(SELECT_INVERT);
 -                              else
 -                                      mouse_nla(SELECT_REPLACE);
 -                      }
 -                      else
 -                              mouse_nlachannels(mval);
 -                      break;
 -
 -              case PADPLUSKEY:
 -                      view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy);
 -                      test_view2d(G.v2d, sa->winx, sa->winy);
 -                      view2d_do_locks(curarea, V2D_LOCK_COPY);
 -                      doredraw= 1;
 -                      break;
 -              case PADMINUS:
 -                      view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy);
 -                      test_view2d(G.v2d, sa->winx, sa->winy);
 -                      view2d_do_locks(curarea, V2D_LOCK_COPY);
 -                      doredraw= 1;
 -                      break;
 -              case MIDDLEMOUSE:
 -              case WHEELUPMOUSE:
 -              case WHEELDOWNMOUSE:
 -                      view2dmove(event);      /* in drawipo.c */
 -                      break;
 -              }
 -      }
 -      
 -      if(doredraw) scrarea_queue_winredraw(curarea);
 -}
 -
  static void set_active_strip(Object *ob, bActionStrip *act)
  {
        bActionStrip *strip;
        
                if(ob->action!=act->act) {
                        if(ob->action) ob->action->id.us--;
 -                      ob->action= act->act;
 -                      ob->action->id.us++;
 -                      
 +                      if(act->act->id.lib) {
 +                              ob->action= NULL;
 +                      }
 +                      else {
 +                              ob->action= act->act;
 +                              id_us_plus(&ob->action->id);
 +                      }                       
                        allqueue(REDRAWIPO, 0);
                        allqueue(REDRAWVIEW3D, 0);
                        allqueue(REDRAWACTION, 0);
@@@ -375,9 -556,11 +375,9 @@@ static void convert_nla(short mval[2]
        }
  }
  
 -
 -static Base *nla_base=NULL;   /* global, bad, bad! put it in nla space later, or recode the 2 functions below (ton) */
 -
  static void add_nla_block(short event)
  {
 +      Object *ob= OBACT;
        bAction *act=NULL;
        bActionStrip *strip;
        int             cur;
        
        /* Link the action to the strip */
        strip->act = act;
 +      id_us_plus(&act->id);
        calc_action_range(strip->act, &strip->actstart, &strip->actend);
        strip->start = G.scene->r.cfra;         /* could be mval[0] another time... */
        strip->end = strip->start + (strip->actend-strip->actstart);
                /* simple prevention of zero strips */
        if(strip->start>strip->end-2) 
                strip->end= strip->start+100;
 -      
 -      strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
 -      
 -      find_stridechannel(nla_base->object, strip);
 -      set_active_strip(nla_base->object, strip);
 -      
        strip->repeat = 1.0;
        
 -      act->id.us++;
 +      strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
        
 -      BLI_addtail(&nla_base->object->nlastrips, strip);
 +      find_stridechannel(ob, strip);
 +      set_active_strip(ob, strip);
 +      strip->object= group_get_member_with_action(ob->dup_group, act);
 +      if(strip->object)
 +              id_lib_extern(&strip->object->id);      /* checks lib data, sets correct flag for saving then */
 +
 +      BLI_addtail(&ob->nlastrips, strip);
  
        BIF_undo_push("Add NLA strip");
  }
@@@ -429,30 -611,72 +429,30 @@@ static void add_nla_databrowse_callback
        /* val is not used, databrowse needs it to optional pass an event */
        short event;
        
 -      if(nla_base==NULL) return;
 +      if(OBACT==NULL) return;
        
        event= G.snla->menunr;  /* set by databrowse or pupmenu */
        
        add_nla_block(event);
  }
  
 -static void add_nlablock(short mval[2])
 +/* Adds strip to to active Object */
 +static void add_nlablock(void)
  {
 -      /* Make sure we are over an object with action */
 -      Base *base;
 -      rctf    rectf;
 -      float ymin, ymax;
 -      float x, y;
 +      Object *ob= OBACT;
        short event;
 -      short nr;
 +      short nr=0;
        char *str;
 -
 -      areamouseco_to_ipoco(G.v2d, mval, &x, &y);
        
 -      mval[0]-=7;
 -      areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
 -      
 -      mval[0]+=14;
 -      areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
 -
 -      ymax = count_nla_levels();      
 -      ymax*= (NLACHANNELHEIGHT + NLACHANNELSKIP);
 -      ymax+= NLACHANNELHEIGHT/2;
 -
 -      for (base=G.scene->base.first; base; base=base->next){
 -              /* Handle object ipo selection */
 -              if (nla_filter(base)) {
 -                      
 -                      /* Area that encloses object name (or ipo) */
 -                      ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
 -
 -                      /* Area that encloses action */
 -                      if (base->object->action)
 -                              ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
 -
 -                      /* Area that encloses nla strips */
 -                      ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*
 -                              (BLI_countlist(&base->object->nlastrips));
 -
 -                      /* Test to see the mouse is in an action area */
 -                      if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
 -                              break;          
 -                      
 -                      ymax=ymin;
 -              }
 -      }       
 -      
 -      /* global... for the call above, because the NLA system seems not to have an 'active strip' stored */
 -      nla_base= base;
 -      
 -      /* Make sure we have an action */
 -      if (!base){
 -              error ("Object has not an Action");
 +      if(ob==NULL) {
 +              error("Need active Object to add NLA strips");
                return;
        }
        
        /* Popup action menu */
 -      IDnames_to_pupstring(&str, "Add Action", NULL, &G.main->action, (ID *)G.scene, &nr);
 +      IDnames_to_pupstring(&str, "Add Action strip", NULL, &G.main->action, (ID *)G.scene, &nr);
        
 -      if(strncmp(str+13, "DataBrow", 8)==0) {
 +      if(nr==-2) {
                MEM_freeN(str);
  
                activate_databrowse((ID *)NULL, ID_AC, 0, 0, &G.snla->menunr, 
                return;                 
        }
        else {
 -              event = pupmenu(str);
 +              event = pupmenu_col(str, 20);
                MEM_freeN(str);
                add_nla_block(event);
        }
 +}
 +
 +/* Adds strip to to active Object */
 +static void relink_active_strip(void)
 +{
 +      Object *ob= OBACT;
 +      bActionStrip *strip;
 +      bAction *act;
 +      short event;
 +      short cur;
 +      char *str;
        
 -      /* Ton: this is a callback for databrowse too
 -         Hos: no, I don't think it is
 -         add_nla_block(0);
 -      */
 +      if(ob==NULL) return;
 +      
 +      for (strip = ob->nlastrips.first; strip; strip=strip->next)
 +              if(strip->flag & ACTSTRIP_ACTIVE)
 +                      break;
 +      
 +      if(strip==NULL) return;
 +      
 +      /* Popup action menu */
 +      IDnames_to_pupstring(&str, "Relink Action strip", NULL, &G.main->action, (ID *)G.scene, NULL);
 +      if(str) {
 +              event = pupmenu_col(str, 20);
 +              MEM_freeN(str);
 +              
 +              for (cur = 1, act=G.main->action.first; act; act=act->id.next, cur++){
 +                      if (cur==event){
 +                              break;
 +                      }
 +              }
 +              
 +              if(act) {
 +                      if(strip->act) strip->act->id.us--;
 +                      strip->act = act;
 +                      id_us_plus(&act->id);
 +                      
 +                      allqueue(REDRAWVIEW3D, 0);
 +                      allqueue(REDRAWACTION, 0);
 +                      allqueue(REDRAWNLA, 0);
 +              }
 +      }
  }
  
 +
 +
  /* Left hand side of channels display, selects objects */
  static void mouse_nlachannels(short mval[2])
  {
@@@ -983,7 -1168,7 +983,7 @@@ void delete_nlachannel_keys(void
        bConstraintChannel *conchan;
        bActionStrip *strip, *nextstrip;
        
-       if (!okee("Erase selected keys"))
+       if (!okee("Erase selected strips and/or keys"))
                return;
        
        for (base = G.scene->base.first; base; base=base->next){
@@@ -1576,190 -1761,3 +1576,190 @@@ void deselect_nlachannels(int test
                base->object->flag= base->flag;
        }       
  }
 +
 +void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 +{
 +      unsigned short event= evt->event;
 +      short val= evt->val;
 +      SpaceNla *snla = curarea->spacedata.first;
 +      int doredraw= 0;
 +      short   mval[2];
 +      float dx,dy;
 +      int     cfra;
 +      short mousebut = L_MOUSE;
 +      
 +      if (curarea->win==0) return;
 +      if (!snla) return;
 +      
 +      if(val) {
 +              if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
 +              
 +              /* swap mouse buttons based on user preference */
 +              if (U.flag & USER_LMOUSESELECT) {
 +                      if (event == LEFTMOUSE) {
 +                              event = RIGHTMOUSE;
 +                              mousebut = L_MOUSE;
 +                      } else if (event == RIGHTMOUSE) {
 +                              event = LEFTMOUSE;
 +                              mousebut = R_MOUSE;
 +                      }
 +              }
 +              
 +              getmouseco_areawin(mval);
 +              
 +              switch(event) {
 +                      case UI_BUT_EVENT:
 +                              do_nlabuts(val); // in drawnla.c
 +                              break;
 +                              
 +                      case HOMEKEY:
 +                              do_nla_buttons(B_NLAHOME);
 +                              break;
 +                              
 +                      case EQUALKEY:
 +                      case PAGEUPKEY:
 +                              shift_nlastrips_up();
 +                              break;
 +                              
 +                      case MINUSKEY:
 +                      case PAGEDOWNKEY:
 +                              shift_nlastrips_down();
 +                              break;
 +                              
 +                      case AKEY:
 +                              if (G.qual & LR_SHIFTKEY){
 +                                      add_nlablock();
 +                                      allqueue (REDRAWNLA, 0);
 +                                      allqueue (REDRAWVIEW3D, 0);
 +                              }
 +                              else{
 +                                      if (mval[0]>=NLAWIDTH)
 +                                              deselect_nlachannel_keys(1);
 +                                      else{
 +                                              deselect_nlachannels(1);
 +                                              allqueue (REDRAWVIEW3D, 0);
 +                                      }
 +                                      allqueue (REDRAWNLA, 0);
 +                                      allqueue (REDRAWIPO, 0);
 +                                      BIF_undo_push("(De)select all NLA");
 +                              }
 +                              break;
 +                              
 +                      case BKEY:
 +                              borderselect_nla();
 +                              break;
 +                              
 +                      case CKEY:
 +                              convert_nla(mval);
 +                              break;
 +                              
 +                      case DKEY:
 +                              if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){
 +                                      duplicate_nlachannel_keys();
 +                                      update_for_newframe_muted();
 +                              }
 +                              break;
 +                              
 +                      case GKEY:
 +                              if (mval[0]>=NLAWIDTH)
 +                                      transform_nlachannel_keys ('g', 0);
 +                              update_for_newframe_muted();
 +                              break;
 +                              
 +                      case NKEY:
 +                              if(G.qual==0) {
 +                                      toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
 +                                      scrarea_queue_winredraw(curarea);
 +                              }
 +                              break;
 +                      case LKEY:
 +                              relink_active_strip();
 +                              break;
 +                              
 +                      case SKEY:
 +                              if(G.qual==LR_ALTKEY) {
 +                                      val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2");
 +                                      if(val==1)
 +                                              reset_action_strips(1);
 +                                      else if(val==2)
 +                                              reset_action_strips(2);
 +                              }
 +                              else if(G.qual & LR_SHIFTKEY) {
 +                                      if(okee("Snap Strips to Frame"))
 +                                              snap_action_strips();
 +                              }
 +                              else {
 +                                      if (mval[0]>=NLAWIDTH)
 +                                              transform_nlachannel_keys ('s', 0);
 +                                      update_for_newframe_muted();
 +                              }
 +                              break;
 +                              
 +                      case DELKEY:
 +                      case XKEY:
 +                              if (mval[0]>=NLAWIDTH)
 +                                      delete_nlachannel_keys ();
 +                              
 +                              update_for_newframe_muted();
 +                              break;
 +                              
 +                              /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above,
 +                              * based on user preference USER_LMOUSESELECT
 +                              */
 +                      case LEFTMOUSE:
 +                              if(view2dmove(LEFTMOUSE))
 +                                      break; // only checks for sliders
 +                              else if (mval[0]>=snla->v2d.mask.xmin) {
 +                                      do {
 +                                              getmouseco_areawin(mval);
 +                                              
 +                                              areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
 +                                              
 +                                              cfra= (int)dx;
 +                                              if(cfra< 1) cfra= 1;
 +                                              
 +                                              if( cfra!=CFRA ) {
 +                                                      CFRA= cfra;
 +                                                      update_for_newframe();
 +                                                      force_draw_all(0);
 +                                              }
 +                                              else PIL_sleep_ms(30);
 +                                              
 +                                      } while(get_mbut() & mousebut);
 +                                      break;
 +                              }
 +                                      /* else pass on! */
 +                              case RIGHTMOUSE:
 +                                      if (mval[0]>=snla->v2d.mask.xmin) {
 +                                              if(G.qual & LR_SHIFTKEY)
 +                                                      mouse_nla(SELECT_INVERT);
 +                                              else
 +                                                      mouse_nla(SELECT_REPLACE);
 +                                      }
 +                                      else
 +                                              mouse_nlachannels(mval);
 +                                      break;
 +                                      
 +                              case PADPLUSKEY:
 +                                      view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy);
 +                                      test_view2d(G.v2d, sa->winx, sa->winy);
 +                                      view2d_do_locks(curarea, V2D_LOCK_COPY);
 +                                      doredraw= 1;
 +                                      break;
 +                              case PADMINUS:
 +                                      view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy);
 +                                      test_view2d(G.v2d, sa->winx, sa->winy);
 +                                      view2d_do_locks(curarea, V2D_LOCK_COPY);
 +                                      doredraw= 1;
 +                                      break;
 +                              case MIDDLEMOUSE:
 +                              case WHEELUPMOUSE:
 +                              case WHEELDOWNMOUSE:
 +                                      view2dmove(event);      /* in drawipo.c */
 +                                      break;
 +              }
 +      }
 +      
 +      if(doredraw) scrarea_queue_winredraw(curarea);
 +}
 +
index fbea7637dd1d22dd909003cf9f9cfacec9cf571d,8a91a60067e10ee50ed8a2488ece6fc9613781b3..97e10fc1585703ea54f49e241ccde5c23565839e
@@@ -157,6 -157,9 +157,9 @@@ void do_layer_buttons(short event
                
                if(G.vd->scenelock) handle_view3d_lock();
                scrarea_queue_winredraw(curarea);
+               
+               /* new layers might need unflushed events events */
+               DAG_scene_update_flags(G.scene, G.vd->lay);     // tags all that moves and flushes
        }
        else {
                if(G.qual & LR_ALTKEY) {
@@@ -742,7 -745,7 +745,7 @@@ void do_view3d_select_object_groupedmen
        case 2: /* Immediate Children */
        case 3: /* Parent */
        case 4: /* Objects on Shared Layers */
 -              select_group((short)event);
 +              select_grouped((short)event);
                break;
        }
        allqueue(REDRAWVIEW3D, 0);