Saturday merger of bf-blender in orange branch.
authorTon Roosendaal <ton@blender.org>
Sat, 17 Dec 2005 20:25:41 +0000 (20:25 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 17 Dec 2005 20:25:41 +0000 (20:25 +0000)
1  2 
source/blender/blenloader/intern/readfile.c
source/blender/include/blendef.h
source/blender/makesdna/DNA_material_types.h
source/blender/src/buttons_shading.c
source/blender/src/header_oops.c
source/blender/src/outliner.c
source/blender/src/space.c
source/blender/src/toets.c

index 5c0843b1873b117e95a341ed90c5c7a12a326397,455c45b00ea2abba039d16309721e096169ffcb1..0cccf770fda0a19428f9f3942bb1b98f0133fd5a
@@@ -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 *****
   *
   */
  
@@@ -228,7 -235,7 +228,7 @@@ typedef struct OldNew 
  typedef struct OldNewMap {
        OldNew *entries;
        int nentries, entriessize;
 -
 +      int sorted;
        int lasthit;
  } OldNewMap;
  
  extern          short freeN(void *vmemh); /* defined in util.h */  
  
  
 -static OldNewMap *oldnewmap_new(void) {
 -      OldNewMap *onm= MEM_mallocN(sizeof(*onm), "OldNewMap");
 -      onm->lasthit= 0;
 -      onm->nentries= 0;
 +static OldNewMap *oldnewmap_new(void) 
 +{
 +      OldNewMap *onm= MEM_callocN(sizeof(*onm), "OldNewMap");
 +      
        onm->entriessize= 1024;
        onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
 -
 +      
        return onm;
  }
  
 -static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) {
 +static int verg_oldnewmap(const void *v1, const void *v2)
 +{
 +      const struct OldNew *x1=v1, *x2=v2;
 +      
 +      if( x1->old > x2->old) return 1;
 +      else if( x1->old < x2->old) return -1;
 +      return 0;
 +}
 +
 +
 +static void oldnewmap_sort(FileData *fd) 
 +{
 +      qsort(fd->libmap->entries, fd->libmap->nentries, sizeof(OldNew), verg_oldnewmap);
 +      fd->libmap->sorted= 1;
 +}
 +
 +/* nr is zero for data, and ID code for libdata */
 +static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) 
 +{
        OldNew *entry;
  
 +      if(oldaddr==NULL || newaddr==NULL) return;
 +      
        if (onm->nentries==onm->entriessize) {
                int osize= onm->entriessize;
                OldNew *oentries= onm->entries;
        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) {
 +/* for libdate, nr has ID code, no increment */
 +static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) 
 +{
        int i;
 -
 -      if (onm->lasthit<onm->nentries-1) {
 -              OldNew *entry= &onm->entries[++onm->lasthit];
 -
 -              if (entry->old==addr) {
 +      
 +      if(addr==NULL) return NULL;
 +      
 +      /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
 +      if(onm->sorted) {
 +              OldNew entry_s, *entry;
 +              
 +              entry_s.old= addr;
 +              
 +              entry= bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
 +              if(entry) {
                        ID *id= entry->newp;
 -
 +                      
                        if (id && (!lib || id->lib)) {
 -                              entry->nr++;
 -
                                return entry->newp;
                        }
                }
        }
 -
 +      
        for (i=0; i<onm->nentries; i++) {
                OldNew *entry= &onm->entries[i];
  
                        ID *id= entry->newp;
  
                        if (id && (!lib || id->lib)) {
 -                              entry->nr++;
 -
                                return entry->newp;
                        }
                }
        return NULL;
  }
  
 -static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, short type) {
 -      int i;
 -
 -      if (onm->lasthit<onm->nentries-1) {
 -              OldNew *entry= &onm->entries[++onm->lasthit];
 -
 -              if (entry->old==addr) {
 -                      ID *id= entry->newp;
 -
 -                      if (id && (GS(id->name) == type)) {
 -                              entry->nr++;
 -
 -                              return entry->newp;
 -                      }
 -              }
 -      }
 -
 -      for (i=0; i<onm->nentries; i++) {
 -              OldNew *entry= &onm->entries[i];
 -
 -              if (entry->old==addr) {
 -                      ID *id= entry->newp;
 -
 -                      if (id && (GS(id->name) == type)) {
 -                              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);
  }
@@@ -442,6 -455,7 +442,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;
  }
  
@@@ -901,19 -897,6 +901,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]=='/')
@@@ -1029,7 -1012,18 +1029,7 @@@ static void *newglobadr(FileData *fd, v
  
  static void *newlibadr(FileData *fd, void *lib, void *adr)            /* only lib data */
  {
 -      return oldnewmap_liblookup_and_inc(fd->libmap, adr, lib);
 -}
 -
 -static void *newlibadr_us_type(FileData *fd, short type, void *adr)   /* only Lib data */
 -{
 -      ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, type);
 -
 -      if (id) {
 -              id->us++;
 -      }
 -
 -      return id;
 +      return oldnewmap_liblookup(fd->libmap, adr, lib);
  }
  
  static void *newlibadr_us(FileData *fd, void *lib, void *adr) /* increases user number */
        return id;
  }
  
 -static void change_libadr(FileData *fd, void *old, void *new)
 +static void change_idid_adr_fd(FileData *fd, void *old, void *new)
  {
        int i;
 -
 -              /* changed one thing here, the old change_libadr
 -               * only remapped addresses that had an id->lib,
 -               * but that doesn't make sense to me... its an
 -               * old pointer, period, it needs to be remapped. - zr
 -               */
 -
 -              /*
 -               * Ton seemed to think it was necessary to look
 -               * through all entries, and not return after finding
 -               * a match, leaving this cryptic comment,
 -               * // no return, maybe there can be more?
 -               *
 -               * That doesn't make sense to me either but I am
 -               * too scared to remove it... it only would make
 -               * sense if two distinct old address map to the
 -               * same new address - obviously that shouldn't happen
 -               * because memory addresses are unique.
 -               *
 -               * The only case it might happen is when two distinct
 -               * libraries are mapped using the same table... this
 -               * won't work to start with... At some point this
 -               * all needs to be made sense of and made understandable,
 -               * but I'm afraid I don't have time now. -zr
 -               *
 -               */
 -    /* the code is nasty, and needs a lot of energy to get into full understanding
 -       again... i now translate dutch comments, maybe that gives me more insight!
 -       But i guess it has to do with the assumption that 2 addresses can be allocated
 -       in different sessions, and therefore be the same... like the remark in the top
 -       of this c file (ton) */
 -
 +      
        for (i=0; i<fd->libmap->nentries; i++) {
                OldNew *entry= &fd->libmap->entries[i];
 -
 -              if (old==entry->newp) {
 +              
 +              if (old==entry->newp && entry->nr==ID_ID) {
                        entry->newp= new;
 +                      if(new) entry->nr= GS( ((ID *)new)->name );
                        break;
                }
        }
  }
  
 +static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, void *new)
 +{
 +      Main *main;
 +      
 +      for(main= mainlist->first; main; main= main->next) {
 +              FileData *fd;
 +              
 +              if(main->curlib) fd= main->curlib->filedata;
 +              else fd= basefd;
 +              
 +              if(fd) {
 +                      change_idid_adr_fd(fd, old, new);
 +              }
 +      }
 +}
  
  /* ********** END OLD POINTERS ****************** */
  /* ********** READ FILE ****************** */
@@@ -1252,7 -1261,6 +1252,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);
        }
@@@ -1379,7 -1387,6 +1379,7 @@@ static void lib_link_pose(FileData *fd
                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;
        }
@@@ -1983,7 -1990,6 +1983,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;
@@@ -2016,6 -2017,8 +2016,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 ***************** */
@@@ -2042,9 -2041,8 +2042,9 @@@ static void lib_link_mesh(FileData *fd
  
                        /* this check added for python created meshes */
                        if(me->mat) {
 -                              for(i=0; i<me->totcol; i++)
 +                              for(i=0; i<me->totcol; i++) {
                                        me->mat[i]= newlibadr_us(fd, me->id.lib, me->mat[i]);
 +                              }
                        }
                        else me->totcol= 0;
  
@@@ -2138,7 -2136,6 +2138,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) {
@@@ -2353,7 -2344,7 +2353,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;
@@@ -2512,18 -2503,19 +2512,18 @@@ 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(fd, sce->id.lib, base->object);
                                
                                /* when save during radiotool, needs cleared */
                                base->flag &= ~OB_RADIO;
                                
 -                              if(base->object==0) {
 +                              if(base->object==NULL) {
                                        printf("LIB ERROR: base removed\n");
                                        BLI_remlink(&sce->base, base);
                                        if(base==sce->basact) sce->basact= 0;
@@@ -3105,25 -3097,10 +3105,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_idid_adr_fd(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);
@@@ -3170,34 -3147,47 +3170,34 @@@ 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;
        }
@@@ -3230,8 -3220,8 +3230,8 @@@ static BHead *read_libblock(FileData *f
                *id_r= id;
        if (!id)
                return blo_nextbhead(fd, bhead);
 -
 -      oldnewmap_insert(fd->libmap, bhead->old, id, 1);
 +      
 +      oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);      /* for ID_ID check */
        BLI_addtail(lb, id);
  
        /* clear first 8 bits */
        case ID_SO: str= "ID_SO"; break;
        case ID_SAMPLE: str= "ID_SAMPLE"; break;
        case ID_GR: str= "ID_GR"; break;
 -      case ID_ID: str= "ID_ID"; break;
        case ID_SEQ: str= "ID_SEQ"; break;
        case ID_AR: str= "ID_AR"; break;
        case ID_AC: str= "ID_AC"; break;
                        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);
@@@ -3437,17 -3428,6 +3437,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;
 +                      }
                }
        }
        
  
  static void lib_link_all(FileData *fd, Main *main)
  {
 +      oldnewmap_sort(fd);
 +      
        lib_link_screen(fd, main);
        lib_link_scene(fd, main);
        lib_link_object(fd, main);
@@@ -5214,7 -5186,10 +5214,10 @@@ BlendFileData *blo_read_file_internal(F
                                 */
                        bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
                        break;
+               case ID_GR:
+                       bhead = blo_nextbhead(fd, bhead);
+                       break;
+                       
                default:
                        bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
                }
        blo_join_main(&fd->mainlist);
  
        lib_link_all(fd, bfd->main);
 +      
        link_global(fd, bfd, fg);       /* as last */
  
        /* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
@@@ -5294,7 -5268,6 +5297,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);
                                        printf("expand: other lib %s\n", lib->name);
                                }
                                else {
 -                                      oldnewmap_insert(fd->libmap, bhead->old, id, 1);
 +                                      //oldnewmap_insert(fd->libmap, bhead->old, id, 1);
 +                                      
 +                                      change_idid_adr_fd(fd, bhead->old, id);
                                        printf("expand: already linked: %s lib: %s\n", id->name, lib->name);
                                }
                        }
                                read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
                        }
                        else {
 -                              oldnewmap_insert(fd->libmap, bhead->old, id, 1);
 +                              /* removed line below... I *really* dont know whatfor (Id is read, so...) 
 +                                 it caused a whole lot of extra and unneeded oldmap entries */
 +                              /* oldnewmap_insert(fd->libmap, bhead->old, id, 1); */
                                /* printf("expand: already read %s\n", id->name); */
                        }
                }
        }
  }
  
 +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);
@@@ -5351,7 -5311,6 +5354,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)
@@@ -5612,7 -5565,6 +5615,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);
        }
@@@ -5776,9 -5728,6 +5779,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;
@@@ -5808,9 -5757,8 +5811,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;
  
@@@ -5985,8 -5933,7 +5988,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 */
@@@ -6122,7 -6068,8 +6125,7 @@@ static void read_libraries(FileData *ba
                                                if (fd->libmap)
                                                        oldnewmap_free(fd->libmap);
  
 -                                              fd->libmap= basefd->libmap;
 -                                              fd->flags|= FD_FLAGS_NOT_MY_LIBMAP;
 +                                              fd->libmap = oldnewmap_new();
                                                
                                                mainptr->curlib->filedata= fd;
                                                mainptr->versionfile= fd->fileversion;
                                                                append_id_part(fd, mainptr, id, &realid);
                                                                if (!realid)
                                                                        printf("LIB ERROR: can't find %s\n", id->name);
 -                                                              change_libadr(fd, id, realid);
 +                                                              
 +                                                              change_idid_adr(mainlist, basefd, id, realid);
  
                                                                MEM_freeN(id);
                                                        }
                        mainptr= mainptr->next;
                }
        }
 -      mainptr= mainl->next;
 -      while(mainptr) {
 -              /* test if there are unread libblocks */
 +      
 +      /* test if there are unread libblocks */
 +      for(mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
                a= set_listbasepointers(mainptr, lbarray);
                while(a--) {
                        ID *id= lbarray[a]->first;
                                        BLI_remlink(lbarray[a], id);
  
                                        printf("LIB ERROR: can't find %s\n", id->name);
 -                                      change_libadr(basefd, id, 0);
 +                                      change_idid_adr(mainlist, basefd, id, NULL);
  
                                        MEM_freeN(id);
                                }
                                id= idn;
                        }
                }
 -
 +      }
 +      
 +      /* do versions, link, and free */
 +      for(mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
                /* some mains still have to be read, then
                 * versionfile is still zero! */
                if(mainptr->versionfile) {
                                do_versions(basefd, NULL, mainptr);
                }
                
 +              if(mainptr->curlib->filedata)
 +                      lib_link_all(mainptr->curlib->filedata, mainptr);
 +              
                if(mainptr->curlib->filedata) blo_freefiledata(mainptr->curlib->filedata);
                mainptr->curlib->filedata= NULL;
  
 -              mainptr= mainptr->next;
        }
  }
  
index 05e06afca4e953f43714ffaa9943d3a8d005619c,cc6e8d054f5974e0800e86d9f48fcd395d57edb0..c79370513fadab99b5c8a7c97d861a43326cfb17
  #define B_OOPSHOME            251
  #define B_OOPSBORDER          252
  #define B_NEWOOPS             253
+ #define B_OOPSVIEWSEL         254
  
  /* INFO: 300 */
  /* watch: also in filesel.c and editobject.c */
  #define B_AUTOFGON            32
  #define B_KNIFE                       0x80
  #define B_PERCENTSUBD 0x40
 -
 +#define B_MESH_X_MIRROR       0x100
  
  /* DISPLAYMODE */
  #define R_DISPLAYVIEW 0
index 8e150b10a823912dd00c1501c878a5d76729d857,451b8ba692f96bea10b0daa13f50cad3bf427218..79d73ff2b996cfdbb3587e11f10f119a0c6975f6
  #ifndef DNA_MATERIAL_TYPES_H
  #define DNA_MATERIAL_TYPES_H
  
 -/*  #include "BLI_listBase.h" */
 -
  #include "DNA_ID.h"
  #include "DNA_scriptlink_types.h"
 +#include "DNA_listBase.h"
  
  #ifndef MAX_MTEX
  #define MAX_MTEX      10
@@@ -46,17 -47,6 +46,17 @@@ struct MTex
  struct Ipo;
  struct Material;
  struct ColorBand;
 +struct Group;
 +
 +typedef struct MaterialLayer {
 +      struct MaterialLayer *next, *prev;
 +      
 +      struct Material *mat;
 +      float blendfac;
 +      short flag, blendmethod, menunr, pad;
 +      int pad2;
 +      
 +} MaterialLayer;
  
  /* WATCH IT: change type? also make changes in ipo.h  */
  
@@@ -64,16 -54,14 +64,16 @@@ typedef struct Material 
        ID id;
        
        short colormodel, lay;          /* lay: for dynamics (old engine, until 2.04) */
 +      /* note, keep this below synced with render_types.h */
        float r, g, b;
        float specr, specg, specb;
        float mirr, mirg, mirb;
        float ambr, ambb, ambg;
 -      
        float amb, emit, ang, spectra, ray_mirror;
        float alpha, ref, spec, zoffs, add;
        float translucency;
 +      /* end synced with render_types.h */
 +      
        float fresnel_mir, fresnel_mir_i;
        float fresnel_tra, fresnel_tra_i;
        float filter;           /* filter added, for raytrace transparency */
        short har;
        char seed1, seed2;
        
 -      int mode; 
 -      int mode2; /* even more material settings :) */
 +      int mode, mode_l;               /* mode_l is the or-ed result of all layer modes */
        short flarec, starc, linec, ringc;
        float hasize, flaresize, subsize, flareboost;
        float strand_sta, strand_end, strand_ease;
 +      float sbias;                    /* shadow bias */
        
        /* for buttons and render*/
        char rgbsel, texact, pr_type, pad;
 -      short pr_back, pr_lamp, septex, pad4;
 -      int pad5;
 +      short pr_back, pr_lamp, septex, ml_flag;        /* ml_flag is for disable base material */
        
        /* shaders */
        short diff_shader, spec_shader;
        float rampfac_col, rampfac_spec;
  
        struct MTex *mtex[10];
 +      ListBase layers;
        struct Ipo *ipo;
 +      struct Group *group;
        
        /* dynamic properties */
        float friction, fh, reflect;
        /* yafray: absorption color, dispersion parameters and material preset menu */
        float YF_ar, YF_ag, YF_ab, YF_dscale, YF_dpwr;
        int YF_dsmp, YF_preset, YF_djit;
 -
 +      
        ScriptLink scriptlink;
  } Material;
  
  #define MA_FULL_OSA           0x800000
  #define MA_TANGENT_STR        0x1000000
  #define MA_SHADBUF            0x2000000
 +              /* note; we drop MA_TANGENT_STR later to become tangent_u */
 +#define MA_TANGENT_V  0x4000000
  
+ #define       MA_MODE_MASK    0x3ffffff       /* all valid mode bits */
  /* diff_shader */
  #define MA_DIFF_LAMBERT               0
  #define MA_DIFF_ORENNAYAR     1
  #define MA_DIFF_TOON          2
 -#define MA_DIFF_MINNAERT        3
 +#define MA_DIFF_MINNAERT    3
 +#define MA_DIFF_FRESNEL     4
  
  /* spec_shader */
  #define MA_SPEC_COOKTORR      0
  #define TEXCO_OSA             512
  #define TEXCO_WINDOW  1024
  #define NEED_UV                       2048
 -      /* optim = use simpler AA */
 -#define TEXCO_OPTIM           4096
 -      /* stored in vertex->accum, 1 D */
 +#define TEXCO_TANGENT 4096
 +      /* still stored in vertex->accum, 1 D */
  #define TEXCO_STRAND  8192
 +#define TEXCO_STRESS  16384
  
  /* mapto */
  #define MAP_COL                       1
  #define MAP_AMB                       2048
  #define MAP_DISPLACE  4096
  #define MAP_WARP              8192
 +#define MAP_LAYER             16384
  
  /* pr_type */
  #define MA_FLAT                       0
  /* pr_back */
  #define MA_DARK                       1
  
 +/* MaterialLayer flag */
 +#define ML_ACTIVE             1
 +#define ML_RENDER             2
 +#define ML_NEG_NORMAL 4
 +#define ML_DIFFUSE            8
 +#define ML_SPECULAR           16
 +#define ML_ALPHA              32
 +
  #endif
  
index f12707d7ac457a83334de2bcb978d4bfa3da7393,246e9daa390250b475e901588cfc131f05676aea..fcbe1a5d71c57ec1fb85feb5eadc79b75566ca38
@@@ -111,9 -111,12 +111,9 @@@ int vergcband(const void *, const void 
  void save_env(char *);
  void drawcolorband(ColorBand *, float , float , float , float );
  
 -
 -static MTex mtexcopybuf;
  static MTex emptytex;
  static int packdummy = 0;
  
 -
  static char *mapto_blendtype_pup(void)
  {
        static char string[1024];
@@@ -376,20 -379,17 +376,20 @@@ static void drawcolorband_cb(void
  {
        ID *id, *idfrom;
        
 -      buttons_active_id(&id, &idfrom);
 +      buttons_active_id(&id, &idfrom);        /* base material, not the matlayer! */
        if( GS(id->name)==ID_TE) {
                Tex *tex= (Tex *)id;
                drawcolorband(tex->coba, 10,145,300,30);
        }
        else if( GS(id->name)==ID_MA) {
                Material *ma= (Material *)id;
 -              if(ma->ramp_show==0)
 -                      drawcolorband(ma->ramp_col, 10,110,300,30);
 -              else
 -                      drawcolorband(ma->ramp_spec, 10,110,300,30);
 +              ma= get_active_matlayer(ma);
 +              if(ma) {
 +                      if(ma->ramp_show==0)
 +                              drawcolorband(ma->ramp_col, 10,110,300,30);
 +                      else
 +                              drawcolorband(ma->ramp_spec, 10,110,300,30);
 +              }
        }
  }
  
@@@ -667,8 -667,12 +667,12 @@@ void do_texbuts(unsigned short event
                        }
  
                        IMB_freeImBuf(tex->ima->ibuf);
-                       tex->ima->ibuf= 0;
+                       tex->ima->ibuf= NULL;
                        tex->ima->ok= 1;
+                       
+                       if(tex->env)
+                               RE_free_envmapdata(tex->env);
+                       
                        allqueue(REDRAWVIEW3D, 0);
                        allqueue(REDRAWIMAGE, 0);
                        BIF_all_preview_changed();
                                do_colorbandbuts(tex->coba, event);
                        }
                        else {
 -                              ma= (Material *)id;
 +                              ma= get_active_matlayer((Material *)id);
                                if(ma->ramp_show==0) do_colorbandbuts(ma->ramp_col, event);
                                else do_colorbandbuts(ma->ramp_spec, event);
                        }
@@@ -1416,7 -1420,7 +1420,7 @@@ static void texture_panel_texture(MTex 
  {
        MTex *mt=NULL;
        uiBlock *block;
 -      ID *id, *idfrom;
 +      ID *id=NULL, *idfrom;
        int a, yco, loos;
        char str[32];
        
        if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return;
  
        /* first do the browse but */
 -      buttons_active_id(&id, &idfrom);
 +      if(mtex)
 +              id= (ID *)mtex->tex;
 +      
 +      if(ma) idfrom= &ma->id;
 +      else if(wrld) idfrom= &wrld->id;
 +      else idfrom= &la->id;
  
        uiBlockSetCol(block, TH_BUT_SETTING2);
        if(ma) {
@@@ -1731,8 -1730,6 +1735,8 @@@ static void radio_panel_render(Radio *r
  
  void do_worldbuts(unsigned short event)
  {
 +      static short mtexcopied=0;
 +      static MTex mtexcopybuf;
        World *wrld;
        MTex *mtex;
        
                        BIF_preview_changed(G.buts);
                }
                break;
 +      case B_WMTEXCOPY:
 +              wrld= G.buts->lockpoin;
 +              if(wrld && wrld->mtex[(int)wrld->texact] ) {
 +                      mtex= wrld->mtex[(int)wrld->texact];
 +                      if(mtex->tex==0) {
 +                              error("No texture available");
 +                      }
 +                      else {
 +                              memcpy(&mtexcopybuf, wrld->mtex[(int)wrld->texact], sizeof(MTex));
 +                              mtexcopied= 1;
 +                      }
 +              }
 +              break;
 +      case B_WMTEXPASTE:
 +              wrld= G.buts->lockpoin;
 +              if(wrld && mtexcopied && mtexcopybuf.tex) {
 +                      if(wrld->mtex[(int)wrld->texact]==0 ) 
 +                              wrld->mtex[(int)wrld->texact]= MEM_mallocN(sizeof(MTex), "mtex"); 
 +                      else if(wrld->mtex[(int)wrld->texact]->tex)
 +                              wrld->mtex[(int)wrld->texact]->tex->id.us--;
 +                      
 +                      memcpy(wrld->mtex[(int)wrld->texact], &mtexcopybuf, sizeof(MTex));
 +                      
 +                      id_us_plus((ID *)mtexcopybuf.tex);
 +                      BIF_undo_push("Paste mapping settings");
 +                      BIF_preview_changed(G.buts);
 +                      scrarea_queue_winredraw(curarea);
 +              }
 +              break;
        }
  }
  
@@@ -1817,10 -1785,10 +1821,10 @@@ static void world_panel_mapto(World *wr
        
        /* MAP TO */
        uiBlockBeginAlign(block);
 -      uiDefButBitS(block, TOG, WOMAP_BLEND, B_MATPRV, "Blend",                10,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour progression of the background");
 +      uiDefButBitS(block, TOG, WOMAP_BLEND, B_MATPRV, "Blend",        10,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour progression of the background");
        uiDefButBitS(block, TOG, WOMAP_HORIZ, B_MATPRV, "Hori",         85,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the horizon");
 -      uiDefButBitS(block, TOG, WOMAP_ZENUP, B_MATPRV, "ZenUp",                160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith above");
 -      uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_MATPRV, "ZenDo",              235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith below");
 +      uiDefButBitS(block, TOG, WOMAP_ZENUP, B_MATPRV, "ZenUp",        160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith above");
 +      uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_MATPRV, "ZenDo",      235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith below");
        uiBlockEndAlign(block);
  
        uiBlockBeginAlign(block);
@@@ -1877,7 -1845,7 +1881,7 @@@ static void world_panel_texture(World *
                uiDefBut(block, TEX, B_IDNAME, "TE:",   100,160,200,19, id->name+2, 0.0, 18.0, 0, 0, "Displays name of the texture block: click to change");
                sprintf(str, "%d", id->us);
                uiDefBut(block, BUT, 0, str,                    196,140,21,19, 0, 0, 0, 0, 0, "Displays number of users of texture: click to make single user");
 -              uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 279,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture");
 +              uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 220,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture");
                if(id->lib) {
                        if(wrld->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB,      219,140,21,19, 0, 0, 0, 0, 0, "");
                        else uiDefIconBut(block, BUT, 0, ICON_PARLIB,   219,140,21,19, 0, 0, 0, 0, 0, "");      
  
        uiBlockSetCol(block, TH_AUTO);
        
 -
 +      /* copy/paste */
 +      uiBlockBeginAlign(block);
 +      uiDefIconBut(block, BUT, B_WMTEXCOPY, ICON_COPYUP,      250,140,25,19, 0, 0, 0, 0, 0, "Copies the mapping settings to the buffer");
 +      uiDefIconBut(block, BUT, B_WMTEXPASTE, ICON_PASTEUP,275,140,25,19, 0, 0, 0, 0, 0, "Pastes the mapping settings from the buffer");
 +              
        /* TEXCO */
        uiBlockBeginAlign(block);
 -      uiDefButS(block, ROW, B_MATPRV, "View",                 100,110,45,20, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Uses global coordinates for the texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "AngMap",               145,110,55,20, &(mtex->texco), 4.0, (float)TEXCO_ANGMAP, 0, 0, "Uses 360 degree angular coordinates, e.g. for spherical light probes");
 -      uiDefButS(block, ROW, B_MATPRV, "Sphere",               200,110,55,20, &(mtex->texco), 4.0, (float)TEXCO_H_SPHEREMAP, 0, 0, "For 360 degree panorama sky, spherical mapped, only top half");
 -      uiDefButS(block, ROW, B_MATPRV, "Tube",                 255,110,45,20, &(mtex->texco), 4.0, (float)TEXCO_H_TUBEMAP, 0, 0, "For 360 degree panorama sky, cylindrical mapped, only top half");
 -      uiDefButS(block, ROW, B_MATPRV, "Object",               100,90,70,20, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
 -      uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "", 170,90,130,20, &(mtex->object), "");
 +      uiDefButS(block, ROW, B_MATPRV, "View",         100,110,100,20, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Uses view vector for the texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Global",       200,110,100,20, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates (interior mist)");
 +      
 +      uiDefButS(block, ROW, B_MATPRV, "AngMap",       100,90,70,20, &(mtex->texco), 4.0, (float)TEXCO_ANGMAP, 0, 0, "Uses 360 degree angular coordinates, e.g. for spherical light probes");
 +      uiDefButS(block, ROW, B_MATPRV, "Sphere",       170,90,65,20, &(mtex->texco), 4.0, (float)TEXCO_H_SPHEREMAP, 0, 0, "For 360 degree panorama sky, spherical mapped, only top half");
 +      uiDefButS(block, ROW, B_MATPRV, "Tube",         235,90,65,20, &(mtex->texco), 4.0, (float)TEXCO_H_TUBEMAP, 0, 0, "For 360 degree panorama sky, cylindrical mapped, only top half");
 +      
 +      uiDefButS(block, ROW, B_MATPRV, "Object",       100,70,70,20, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
 +      uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "", 170,70,130,20, &(mtex->object), "");
  
        uiBlockBeginAlign(block);
 -      uiDefButF(block, NUM, B_MATPRV, "dX",           100,50,100,19, mtex->ofs, -20.0, 20.0, 10, 0, "Fine tunes texture mapping X coordinate");
 -      uiDefButF(block, NUM, B_MATPRV, "dY",           100,30,100,19, mtex->ofs+1, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Y coordinate");
 -      uiDefButF(block, NUM, B_MATPRV, "dZ",           100,10,100,19, mtex->ofs+2, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Z coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "dX",           100,40,100,19, mtex->ofs, -20.0, 20.0, 10, 0, "Fine tunes texture mapping X coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "dY",           100,20,100,19, mtex->ofs+1, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Y coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "dZ",           100, 0,100,19, mtex->ofs+2, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Z coordinate");
        uiBlockBeginAlign(block);
 -      uiDefButF(block, NUM, B_MATPRV, "sizeX",        200,50,100,19, mtex->size, -10.0, 10.0, 10, 0, "Sets scaling for the texture's X size");
 -      uiDefButF(block, NUM, B_MATPRV, "sizeY",        200,30,100,19, mtex->size+1, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Y size");
 -      uiDefButF(block, NUM, B_MATPRV, "sizeZ",        200,10,100,19, mtex->size+2, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Z size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeX",        200,40,100,19, mtex->size, -10.0, 10.0, 10, 0, "Sets scaling for the texture's X size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeY",        200,20,100,19, mtex->size+1, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Y size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeZ",        200, 0,100,19, mtex->size+2, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Z size");
        
  }
  
@@@ -2020,12 -1981,16 +2024,12 @@@ static void world_panel_amb_occ(World *
  static void world_panel_world(World *wrld)
  {
        uiBlock *block;
 -      ID *id, *idfrom;
        
        block= uiNewBlock(&curarea->uiblocks, "world_panel_world", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "World", "World", 320, 0, 318, 204)==0) return;
  
 -      /* first do the browse but */
 -      buttons_active_id(&id, &idfrom);
 -
        uiBlockSetCol(block, TH_BUT_SETTING2);
 -      std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, id, idfrom, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA);
 +      std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, (ID *)wrld, (ID *)G.scene, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA);
  
        if(wrld==NULL) return;
        
@@@ -2087,8 -2052,6 +2091,8 @@@ static void world_panel_preview(World *
  
  void do_lampbuts(unsigned short event)
  {
 +      static short mtexcopied=0;
 +      static MTex mtexcopybuf;
        Lamp *la;
        MTex *mtex;
  
                allqueue(REDRAWBUTSSHADING, 0);
                allqueue(REDRAWVIEW3D, 0);      
                break;
 +      case B_LMTEXCOPY:
 +              la= G.buts->lockpoin;
 +              if(la && la->mtex[(int)la->texact] ) {
 +                      mtex= la->mtex[(int)la->texact];
 +                      if(mtex->tex==0) {
 +                              error("No texture available");
 +                      }
 +                      else {
 +                              memcpy(&mtexcopybuf, la->mtex[(int)la->texact], sizeof(MTex));
 +                              mtexcopied= 1;
 +                      }
 +              }
 +              break;
 +      case B_LMTEXPASTE:
 +              la= G.buts->lockpoin;
 +              if(la && mtexcopied && mtexcopybuf.tex) {
 +                      if(la->mtex[(int)la->texact]==0 ) 
 +                              la->mtex[(int)la->texact]= MEM_mallocN(sizeof(MTex), "mtex"); 
 +                      else if(la->mtex[(int)la->texact]->tex)
 +                              la->mtex[(int)la->texact]->tex->id.us--;
 +
 +                      memcpy(la->mtex[(int)la->texact], &mtexcopybuf, sizeof(MTex));
 +                      
 +                      id_us_plus((ID *)mtexcopybuf.tex);
 +                      BIF_undo_push("Paste mapping settings");
 +                      BIF_preview_changed(G.buts);
 +                      scrarea_queue_winredraw(curarea);
 +              }
 +              break;
 +              
        }
        
        if(event) freefastshade();
@@@ -2258,7 -2191,7 +2262,7 @@@ static void lamp_panel_texture(Object *
                uiDefBut(block, TEX, B_IDNAME, "TE:",   100,160,200,19, id->name+2, 0.0, 18.0, 0, 0, "Displays name of the texture block: click to change");
                sprintf(str, "%d", id->us);
                uiDefBut(block, BUT, 0, str,                    196,140,21,19, 0, 0, 0, 0, 0, "Displays number of users of texture: click to make single user");
 -              uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 241,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture");
 +              uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 221,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture");
                if(id->lib) {
                        if(la->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB,        219,140,21,19, 0, 0, 0, 0, 0, "");
                        else uiDefIconBut(block, BUT, 0, ICON_PARLIB,   219,140,21,19, 0, 0, 0, 0, 0, "");      
        else 
                uiDefButS(block, TOG, B_LTEXBROWSE, "Add New" ,100, 160, 200, 19, &(G.buts->texnr), -1.0, 32767.0, 0, 0, "Adds a new texture datablock");
  
 +      /* copy/paste */
 +      uiBlockBeginAlign(block);
 +      uiDefIconBut(block, BUT, B_LMTEXCOPY, ICON_COPYUP,      250,140,25,19, 0, 0, 0, 0, 0, "Copies the mapping settings to the buffer");
 +      uiDefIconBut(block, BUT, B_LMTEXPASTE, ICON_PASTEUP,    275,140,25,19, 0, 0, 0, 0, 0, "Pastes the mapping settings from the buffer");
 +      
        /* TEXCO */
        uiBlockSetCol(block, TH_AUTO);
        uiBlockBeginAlign(block);
@@@ -2459,6 -2387,7 +2463,6 @@@ static void lamp_panel_yafray(Object *o
  static void lamp_panel_lamp(Object *ob, Lamp *la)
  {
        uiBlock *block;
 -      ID *id, *idfrom;
        float grid= 0.0;
        short xco;
        
  
        uiSetButLock(la->id.lib!=0, "Can't edit library data");
  
 -      /* first do the browse but */
 -      buttons_active_id(&id, &idfrom);
 -
        uiBlockSetCol(block, TH_BUT_SETTING2);
 -      xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, id, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0);  
 +      xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, (ID *)la, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0);    
  
        uiBlockSetCol(block, TH_AUTO);
        uiDefButF(block, NUM,B_LAMPREDRAW,"Dist:", xco,180,300-xco,20,&la->dist, 0.01, 5000.0*grid, 100, 0, "Sets the distance value at which light intensity is half");
@@@ -2559,20 -2491,12 +2563,20 @@@ static void lamp_panel_preview(Object *
  void do_matbuts(unsigned short event)
  {
        static short mtexcopied=0;
 +      static MTex mtexcopybuf;
        Material *ma;
        MTex *mtex;
  
 +      /* all operations default on active material layer here */
 +      /* but this also gets called for lamp and world... */
 +      ma= G.buts->lockpoin;
 +      if(ma && GS(ma->id.name)==ID_MA)
 +              ma = get_active_matlayer(ma);
 +      else
 +              ma= NULL;
 +      
        switch(event) {
        case B_MAT_YF_PRESET: {
 -              ma = G.buts->lockpoin;
                switch (ma->YF_preset) {
                        case 0:
                                /* normal mode, no reflection/refraction */
        case B_MATHALO:
                /* when halo is disabled, clear star flag, this is the same as MA_FACETEXTURE <blush> */
                /* same for 'xtreme alpha' which is 'only shadow' */
 -              ma= G.buts->lockpoin;
                if((ma->mode & MA_HALO)==0) {
                        ma->mode &= ~(MA_STAR|MA_HALO_XALPHA|MA_ZINV);
                }
                shade_buttons_change_3d();
                break;
        case B_TEXCLEAR:
 -              ma= G.buts->lockpoin;
                mtex= ma->mtex[(int) ma->texact ];
                if(mtex) {
                        if(mtex->tex) mtex->tex->id.us--;
                }
                break;
        case B_MTEXCOPY:
 -              ma= G.buts->lockpoin;
                if(ma && ma->mtex[(int)ma->texact] ) {
                        mtex= ma->mtex[(int)ma->texact];
                        if(mtex->tex==0) {
                }
                break;
        case B_MTEXPASTE:
 -              ma= G.buts->lockpoin;
                if(ma && mtexcopied && mtexcopybuf.tex) {
 -                      if(ma->mtex[(int)ma->texact]==0 ) ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); 
 +                      if(ma->mtex[(int)ma->texact]==0 ) 
 +                              ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); 
 +                      else if(ma->mtex[(int)ma->texact]->tex)
 +                              ma->mtex[(int)ma->texact]->tex->id.us--;
 +
                        memcpy(ma->mtex[(int)ma->texact], &mtexcopybuf, sizeof(MTex));
                        
                        id_us_plus((ID *)mtexcopybuf.tex);
                }
                break;
        case B_MATLAY:
 -              ma= G.buts->lockpoin;
                if(ma && ma->lay==0) {
                        ma->lay= 1;
                        scrarea_queue_winredraw(curarea);
                }
                break;
        case B_MATZTRANSP:
 -              ma= G.buts->lockpoin;
                if(ma) {
                        ma->mode &= ~MA_RAYTRANSP;
                        allqueue(REDRAWBUTSSHADING, 0);
                }
                break;
        case B_MATRAYTRANSP:
 -              ma= G.buts->lockpoin;
                if(ma) {
                        ma->mode &= ~MA_ZTRA;
                        allqueue(REDRAWBUTSSHADING, 0);
                }
                break;
        case B_MATCOLORBAND:
 -              ma= G.buts->lockpoin;
                if(ma) {
                        if(ma->mode & MA_RAMP_COL)
                                if(ma->ramp_col==NULL) ma->ramp_col= add_colorband();
                        shade_buttons_change_3d();
                }
                break;
 -
 +      case B_MAT_LAYERBROWSE:
 +              ma= G.buts->lockpoin;   /* use base material instead */
 +              if(ma) {
 +                      MaterialLayer *ml;
 +                      
 +                      /* the one with a menu set is the browser */
 +                      for(ml= ma->layers.first; ml; ml= ml->next) {
 +                              if(ml->menunr) {
 +                                      if(ml->menunr==32767) {
 +                                              if(ml->mat) {
 +                                                      ml->mat->id.us--;
 +                                                      ml->mat= copy_material(ml->mat);
 +                                              }
 +                                              else ml->mat= add_material("Layer");
 +                                      }
 +                                      else {
 +                                              ml->mat= BLI_findlink(&G.main->mat, ml->menunr-1);
 +                                              ml->mat->id.us++;
 +                                      }
 +                                      allqueue(REDRAWBUTSSHADING, 0);
 +                                      BIF_all_preview_changed();
 +                                      
 +                                      break;
 +                              }
 +                      }
 +              }
 +              break;
        }
  }
  
@@@ -2817,7 -2719,7 +2821,7 @@@ static void material_panel_map_to(Mater
        uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir",      60,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
        uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha",         110,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
        uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit",           160,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
 -      uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "Translu",     205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the translucency value");
 +      uiDefButBitS(block, TOG3, MAP_LAYER, B_MATPRV, "Layer",         205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value");
        uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp",               265,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
        uiBlockEndAlign(block);
        
@@@ -2856,29 -2758,26 +2860,29 @@@ static void material_panel_map_input(Ob
        
        /* TEXCO */
        uiBlockBeginAlign(block);
 -      uiDefButS(block, ROW, B_MATPRV, "UV",                   630,166,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "Object",               670,166,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
 -      uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "",745,166,163,18, &(mtex->object), "");
 +      uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
 +      uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "",750,180,158,18, &(mtex->object), "");
        
 -      uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,146,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "Orco",                 675,146,50,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original coordinates of the mesh");
 +      uiDefButS(block, ROW, B_MATPRV, "UV",                   630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Orco",                 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
        if( give_parteff(ob) )
 -              uiDefButS(block, ROW, B_MATPRV, "Strand",       725,146,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
 +              uiDefButS(block, ROW, B_MATPRV, "Strand",       725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
        else
 -              uiDefButS(block, ROW, B_MATPRV, "Stick",                725,146,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "Win",                  775,146,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,146,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
 -      uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,146,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
 +              uiDefButS(block, ROW, B_MATPRV, "Stick",        725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Win",                  775,160,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
 +      uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
 +      
 +      uiDefButS(block, ROW, B_MATPRV, "Stress",               630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
 +      uiDefButS(block, ROW, B_MATPRV, "Tangent",              700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses te optional tangent vector as texture coordinates");
  
        /* COORDS */
        uiBlockBeginAlign(block);
 -      uiDefButC(block, ROW, B_MATPRV, "Flat",                 630,114,48,18, &(mtex->mapping), 5.0, (float)MTEX_FLAT, 0, 0, "Maps X and Y coordinates directly");
 -      uiDefButC(block, ROW, B_MATPRV, "Cube",                 681,114,50,18, &(mtex->mapping), 5.0, (float)MTEX_CUBE, 0, 0, "Maps using the normal vector");
 -      uiDefButC(block, ROW, B_MATPRV, "Tube",                 630,94,48,18, &(mtex->mapping), 5.0, (float)MTEX_TUBE, 0, 0, "Maps with Z as central axis (tube-like)");
 -      uiDefButC(block, ROW, B_MATPRV, "Sphe",                 681,94,50,18, &(mtex->mapping), 5.0, (float)MTEX_SPHERE, 0, 0, "Maps with Z as central axis (sphere-like)");
 +      uiDefButC(block, ROW, B_MATPRV, "Flat",                 630,115,48,19, &(mtex->mapping), 5.0, (float)MTEX_FLAT, 0, 0, "Maps X and Y coordinates directly");
 +      uiDefButC(block, ROW, B_MATPRV, "Cube",                 681,115,50,19, &(mtex->mapping), 5.0, (float)MTEX_CUBE, 0, 0, "Maps using the normal vector");
 +      uiDefButC(block, ROW, B_MATPRV, "Tube",                 630,95,48,19, &(mtex->mapping), 5.0, (float)MTEX_TUBE, 0, 0, "Maps with Z as central axis (tube-like)");
 +      uiDefButC(block, ROW, B_MATPRV, "Sphe",                 681,95,50,19, &(mtex->mapping), 5.0, (float)MTEX_SPHERE, 0, 0, "Maps with Z as central axis (sphere-like)");
  
        uiBlockBeginAlign(block);
        for(b=0; b<3; b++) {
        }
        
        uiBlockBeginAlign(block);
 -      uiDefButF(block, NUM, B_MATPRV, "ofsX",         778,114,130,18, mtex->ofs, -10.0, 10.0, 10, 0, "Fine tunes texture mapping X coordinate");
 -      uiDefButF(block, NUM, B_MATPRV, "ofsY",         778,94,130,18, mtex->ofs+1, -10.0, 10.0, 10, 0, "Fine tunes texture mapping Y coordinate");
 -      uiDefButF(block, NUM, B_MATPRV, "ofsZ",         778,74,130,18, mtex->ofs+2, -10.0, 10.0, 10, 0, "Fine tunes texture mapping Z coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "ofsX",         778,115,130,19, mtex->ofs, -10.0, 10.0, 10, 0, "Fine tunes texture mapping X coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "ofsY",         778,95,130,19, mtex->ofs+1, -10.0, 10.0, 10, 0, "Fine tunes texture mapping Y coordinate");
 +      uiDefButF(block, NUM, B_MATPRV, "ofsZ",         778,75,130,19, mtex->ofs+2, -10.0, 10.0, 10, 0, "Fine tunes texture mapping Z coordinate");
        uiBlockBeginAlign(block);
 -      uiDefButF(block, NUM, B_MATPRV, "sizeX",        778,50,130,18, mtex->size, -100.0, 100.0, 10, 0, "Sets scaling for the texture's X size");
 -      uiDefButF(block, NUM, B_MATPRV, "sizeY",        778,30,130,18, mtex->size+1, -100.0, 100.0, 10, 0, "Sets scaling for the texture's Y size");
 -      uiDefButF(block, NUM, B_MATPRV, "sizeZ",        778,10,130,18, mtex->size+2, -100.0, 100.0, 10, 0, "Sets scaling for the texture's Z size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeX",        778,50,130,19, mtex->size, -100.0, 100.0, 10, 0, "Sets scaling for the texture's X size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeY",        778,30,130,19, mtex->size+1, -100.0, 100.0, 10, 0, "Sets scaling for the texture's Y size");
 +      uiDefButF(block, NUM, B_MATPRV, "sizeZ",        778,10,130,19, mtex->size+2, -100.0, 100.0, 10, 0, "Sets scaling for the texture's Z size");
        uiBlockEndAlign(block);
  
  }
@@@ -3128,7 -3027,7 +3132,7 @@@ static void material_panel_shading(Mate
                uiBlockEndAlign(block);
        }
        else {
 -              char *str1= "Diffuse Shader%t|Lambert %x0|Oren-Nayar %x1|Toon %x2|Minnaert %x3";
 +              char *str1= "Diffuse Shader%t|Lambert %x0|Oren-Nayar %x1|Toon %x2|Minnaert %x3|Fresnel %x4";
                char *str2= "Specular Shader%t|CookTorr %x0|Phong %x1|Blinn %x2|Toon %x3|WardIso %x4";
                
                /* diff shader buttons */
                }
                else if(ma->diff_shader==MA_DIFF_MINNAERT) 
                        uiDefButF(block, NUMSLI, B_MATPRV, "Dark:",90,160, 150,19, &(ma->darkness), 0.0, 2.0, 0, 0, "Sets Minnaert darkness");
 +              else if(ma->diff_shader==MA_DIFF_FRESNEL) {
 +                      uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel:",  90, 160,150,19, &(ma->param[1]), 0.0, 5.0, 0, 0, "Power of Fresnel");
 +                      uiDefButF(block, NUMSLI, B_MATPRV, "Fac:",90,140,150,19, &(ma->param[0]), 1.0, 5.0, 0, 0, "Blending factor");
 +              }
                uiBlockEndAlign(block);
                
                /* spec shader buttons */
                        uiDefButF(block, NUMSLI, B_MATPRV, "rms:",     90, 100,150,19, &(ma->rms), 0.0, 0.4, 0, 0, "Sets the standard deviation of surface slope");             
                /* default shading variables */
                uiBlockBeginAlign(block);
 -              uiDefButF(block, NUMSLI, B_DIFF, "Translucency ",       9,30,301,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Amount of diffuse shading of the back side");
 +              uiDefButF(block, NUMSLI, B_DIFF, "Tralu ",      9,30,150,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Translucency, amount of diffuse shading of the back side");
 +              uiDefButF(block, NUMSLI, B_DIFF, "SBias ",      159,30,151,19, &(ma->sbias), 0.0, 0.25, 10, 2, "Shadow bias, to prevent terminator problems on shadow boundary");
                uiDefButF(block, NUMSLI, B_MATPRV, "Amb ",              9,10,150,19, &(ma->amb), 0.0, 1.0, 0, 0, "Sets the amount of global ambient color the material receives");
 -              uiDefButF(block, NUMSLI, B_MATPRV, "Emit ",             160,10,150,19, &(ma->emit), 0.0, 1.0, 0, 0, "Sets the amount of light the material emits");
 +              uiDefButF(block, NUMSLI, B_MATPRV, "Emit ",             159,10,151,19, &(ma->emit), 0.0, 1.0, 0, 0, "Sets the amount of light the material emits");
                uiBlockEndAlign(block);
  
                uiBlockSetCol(block, TH_BUT_SETTING1);
                uiBlockBeginAlign(block);
 -              uiDefButBitI(block, TOG, MA_TRACEBLE, 0,"Traceable",            245,160,65,18, &(ma->mode), 0, 0, 0, 0, "Makes material to being detected by ray tracing");
 -              uiDefButBitI(block, TOG, MA_SHADBUF, 0, "Shadbuf",                      245,142,65,18, &(ma->mode), 0, 0, 0, 0, "Makes material to cast shadows with shadow buffers");
 +              uiDefButBitI(block, TOG, MA_TRACEBLE, B_NOP,"Traceable",                245,160,65,18, &(ma->mode), 0, 0, 0, 0, "Makes material to being detected by ray tracing");
 +              uiDefButBitI(block, TOG, MA_SHADBUF, B_NOP,     "Shadbuf",                      245,142,65,18, &(ma->mode), 0, 0, 0, 0, "Makes material to cast shadows with shadow buffers");
  
                uiBlockBeginAlign(block);
 -              uiDefButBitI(block, TOG, MA_SHADOW, 0,  "Shadow",                       245,120,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows");
 -              uiDefButBitI(block, TOG, MA_SHADOW_TRA, 0, "TraShadow",         245,100,65,19, &(ma->mode), 0, 0, 0, 0, "Receives transparent shadows based at material color and alpha");
 -              uiDefButBitI(block, TOG, MA_RAYBIAS, 0, "Bias",                         245,80,65,19, &(ma->mode), 0, 0, 0, 0, "Prevents ray traced shadow errors with phong interpolated normals (terminator problem)");
 +              uiDefButBitI(block, TOG, MA_SHADOW, B_NOP,      "Shadow",                       245,120,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows");
 +              uiDefButBitI(block, TOG, MA_SHADOW_TRA, B_NOP, "TraShadow",             245,100,65,19, &(ma->mode), 0, 0, 0, 0, "Recieves transparent shadows based at material color and alpha");
 +              uiDefButBitI(block, TOG, MA_RAYBIAS, B_NOP, "Bias",                             245,80,65,19, &(ma->mode), 0, 0, 0, 0, "Prevents ray traced shadow errors with phong interpolated normals (terminator problem)");
                uiBlockEndAlign(block);
  
 -              uiDefButBitI(block, TOG, MA_RADIO, 0,   "Radio",                        245,55,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosity rendering");
 +              uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_NOP, "GR:", 9, 55, 150, 19, &ma->group, "Limit Lighting to Lamps in this Group"); 
 +              
 +              uiDefButBitI(block, TOG, MA_TANGENT_V, B_MATPRV, "Tangent V",           170,55,65,19, &(ma->mode), 0, 0, 0, 0, "Use the tangent vector in V direction for shading");
 +              uiDefButBitI(block, TOG, MA_RADIO, B_NOP,       "Radio",                        245,55,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosity rendering");
  
        }
 +}
  
 +static void matlayer_add(void *ma_v, void *ml_v)
 +{
 +      Material *ma= ma_v;
 +      MaterialLayer *ml= ml_v, *mlnew;
 +      
 +      mlnew= MEM_callocN(sizeof(MaterialLayer), "mat layer");
 +      
 +      if(ml==NULL) 
 +              BLI_addhead(&ma->layers, mlnew);
 +      else
 +              BLI_insertlink(&ma->layers, ml, mlnew);
 +      
 +      mlnew->blendfac= 0.5f;
 +      mlnew->flag= ML_RENDER|ML_DIFFUSE|ML_SPECULAR;
 +      
 +      BIF_undo_push("Add Material Layer");
 +      allqueue(REDRAWBUTSSHADING, 0);
 +}
 +
 +static void matlayer_moveUp(void *ma_v, void *ml_v)
 +{
 +      Material *ma= ma_v;
 +      MaterialLayer *ml= ml_v;
 +
 +      if (ml->prev) {
 +              BLI_remlink(&ma->layers, ml);
 +              BLI_insertlink(&ma->layers, ml->prev->prev, ml);
 +      }
 +      
 +      BIF_undo_push("Move Material Layer");
 +}
 +
 +static void matlayer_moveDown(void *ma_v, void *ml_v)
 +{
 +      Material *ma= ma_v;
 +      MaterialLayer *ml= ml_v;
 +      
 +      if (ml->next) {
 +              BLI_remlink(&ma->layers, ml);
 +              BLI_insertlink(&ma->layers, ml->next, ml);
 +      }
 +      
 +      BIF_undo_push("Move Material Layer");
  }
  
 +static void matlayer_del(void *ma_v, void *ml_v)
 +{
 +      Material *ma= ma_v;
 +      MaterialLayer *ml= ml_v;
 +      
 +      BLI_remlink(&ma->layers, ml);
 +      if(ml->mat) ml->mat->id.us--;
 +      MEM_freeN(ml);
 +
 +      BIF_undo_push("Delete Material Layer");
 +}
 +
 +static void matlayer_active(void *ma_v, void *ml_v)
 +{
 +      Material *ma= ma_v;
 +      MaterialLayer *ml;
 +      
 +      for(ml= ma->layers.first; ml; ml= ml->next) {
 +              if(ml==ml_v)
 +                      ml->flag |= ML_ACTIVE;
 +              else
 +                      ml->flag &= ~ML_ACTIVE;
 +      }
 +      BIF_undo_push("Activate Material Layer");
 +}
 +
 +static void matlayer_alone(void *ml_v, void *unused)
 +{
 +      MaterialLayer *ml= ml_v;
 +      
 +      ml->mat= copy_material(ml->mat);
 +
 +      BIF_undo_push("Single user material");
 +      allqueue(REDRAWBUTSSHADING, 0);
 +      allqueue(REDRAWOOPS, 0);
 +}
 +
 +
 +static void material_panel_layers(Material *ma)
 +{
 +      uiBlock *block;
 +      uiBut *but;
 +      MaterialLayer *ml;
 +      int yco= 155, rb_col;
 +      char *strp;
 +      
 +      block= uiNewBlock(&curarea->uiblocks, "material_panel_layers", UI_EMBOSS, UI_HELV, curarea->win);
 +      uiNewPanelTabbed("Preview", "Material");
 +      if(uiNewPanel(curarea, block, "Layers", "Material", 0, 0, 318, 204)==0) return;
 +      
 +      uiNewPanelHeight(block, 204);
 +      
 +      /* Active button for current material */
 +      uiBlockBeginAlign(block);
 +      for(ml= ma->layers.first; ml; ml= ml->next)
 +              if(ml->flag & ML_ACTIVE) break;
 +      
 +      if(ml==NULL)
 +              but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL,      10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material");
 +      else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ",               10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material");
 +      uiButSetFunc(but, matlayer_active, ma, NULL);
 +      
 +      /* Enable/disable for current material */
 +      if(ma->ml_flag & ML_RENDER)
 +              uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT,       30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material");
 +      else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material");
 +      
 +      uiBlockEndAlign(block);
 +      /* label */
 +      uiDefBut(block, LABEL, B_NOP, ma->id.name+2,                    60, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
 +      /* add layer */
 +      but= uiDefBut(block, BUT, B_NOP, "Add Layer", 200, 180,110,20, NULL, 0, 0, 0, 0, "Add a new Material Layer");
 +      uiButSetFunc(but, matlayer_add, ma, NULL);
 +
 +      
 +      for(ml= ma->layers.first; ml; ml= ml->next) {
 +              
 +              /* rounded header */
 +              rb_col= (ml->flag & ML_ACTIVE)?40:20;
 +              uiDefBut(block, ROUNDBOX, B_DIFF, "", 8, yco-48, 304, 71, NULL, 5.0, 0.0, 3 , rb_col-20, ""); 
 +              
 +              /* Active button */
 +              uiBlockBeginAlign(block);
 +              if(ml->flag & ML_ACTIVE)
 +                      but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL,      10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer");
 +              else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ",               10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer");
 +              uiButSetFunc(but, matlayer_active, ma, ml);
 +              
 +              /* enable/disable button */
 +              if(ml->flag & ML_RENDER)
 +                      uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT,       30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer");
 +              else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer");
 +              
 +              uiBlockBeginAlign(block);
 +              
 +              /* browse button */
 +              IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), (ID *)ma, NULL);
 +              ml->menunr= 0;
 +              uiDefButS(block, MENU, B_MAT_LAYERBROWSE, strp, 60,yco,20,20, &ml->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
 +              if(strp) MEM_freeN(strp);
 +                      
 +              /* name and users */
 +              if(ml->mat) {
 +                      int width;
 +                      
 +                      if(ml->mat->id.us>1) width= 120;
 +                      else width= 140;
 +                      but= uiDefBut(block, TEX, B_IDNAME, "MA:",80, yco, width, 20, ml->mat->id.name+2, 0.0, 19.0, 0, 0, "Rename Material");
 +                      uiButSetFunc(but, test_idbutton_cb, ml->mat->id.name, NULL);
 +                      
 +                      if(ml->mat->id.us>1) {
 +                              char str1[32];
 +                              sprintf(str1, "%d", ml->mat->id.us);
 +                              but= uiDefBut(block, BUT, B_NOP, str1, 200,yco,20,20, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
 +                              uiButSetFunc(but, matlayer_alone, ml, NULL);
 +                      }
 +              }
 +              else
 +                      uiDefBut(block, LABEL, B_NOP, "No Material",80, yco, 140, 20, NULL, 0.0, 0.0, 0, 0, "");
 +                      
 +              /* add new */
 +              but= uiDefBut(block, BUT, B_NOP, "Add", 220, yco,30,20, NULL, 0, 0, 0, 0, "Add a new Material Layer");
 +              uiButSetFunc(but, matlayer_add, ma, ml);
 +              
 +              /* move up/down/delete */
 +              but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_UP, 250, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer up");
 +              uiButSetFunc(but, matlayer_moveUp, ma, ml);
 +              
 +              but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_DOWN, 270, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer down");
 +              uiButSetFunc(but, matlayer_moveDown, ma, ml);
 +              
 +              but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_X, 290, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete material layer");
 +              uiButSetFunc(but, matlayer_del, ma, ml);
 +              
 +              /* blend slider and operation */
 +              uiBlockBeginAlign(block);
 +              yco-= 25;
 +              uiDefButS(block, MENU, B_MATPRV, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Divide %x5|Difference %x6|Darken %x7|Lighten %x8",
 +                                                                                                      35,yco,100,20, &ml->blendmethod, 0, 0, 0, 0, "Blending method for Ramp (uses alpha in Colorband)");
 +              uiDefButF(block, NUMSLI, B_MATPRV, "Blend:",135,yco,175,20, &ml->blendfac, 0.0, 1.0, 100, 0, "Blending factor");
 +              
 +              /* output */
 +              yco-=20;
 +              uiDefButBitS(block, TOG, ML_DIFFUSE, B_MATPRV,  "Diff",         35,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Diffuse");
 +              uiDefButBitS(block, TOG, ML_SPECULAR, B_MATPRV, "Spec", 85,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Specular");
 +              uiDefButBitS(block, TOG, ML_ALPHA, B_MATPRV, "Alpha",           135,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Alpha");
 +              uiDefButBitS(block, TOG, ML_NEG_NORMAL, B_MATPRV, "Negate Normal",      185,yco,125,20, &ml->flag, 0, 0, 0, 0, "Negate normal for this layer");
 +              
 +              yco-= 30;
 +              
 +              uiBlockEndAlign(block);
 +      }
 +      
 +      if(yco < 0) uiNewPanelHeight(block, 204-yco);
 +
 +}
 +
 +
  static void material_panel_ramps(Material *ma)
  {
        uiBlock *block;
@@@ -3478,7 -3167,7 +3482,7 @@@ static void material_panel_material(Obj
        if(uiNewPanel(curarea, block, "Material", "Material", 320, 0, 318, 204)==0) return;
  
        /* first do the browse but */
 -      buttons_active_id(&id, &idfrom);
 +      buttons_active_id(&id, &idfrom);        /* base material, not the matlayer! */
  
        uiBlockSetCol(block, TH_BUT_SETTING2);
        std_libbuttons(block, 8, 200, 0, NULL, B_MATBROWSE, id, idfrom, &(G.buts->menunr), B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME, B_KEEPDATA);
        if(ob->totcol==0) return;
        uiSetButLock(id->lib!=0, "Can't edit library data");
  
 -      ma= give_current_material(ob, ob->actcol);      
 -      if(ma==0) return;       
 +      ma= get_active_matlayer(ma);
 +      if(ma==NULL) return;    
        
        if(ma->dynamode & MA_DRAW_DYNABUTS) {
                uiBlockBeginAlign(block);
@@@ -3639,30 -3328,23 +3643,30 @@@ void material_panels(
                material_panel_material(ob, ma);
                
                if(ma) {
 -                      material_panel_ramps(ma);
 -                      material_panel_shading(ma);
 -                      if (G.scene->r.renderer==R_INTERN)
 -                              material_panel_tramir(ma);
 -                      else {
 -                              if (ma->YF_ar==0.f) {
 -                                      ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
 -                                      ma->YF_dscale = 1;
 -                              }
 -                              material_panel_tramir_yafray(ma);
 -                      }
 -                      material_panel_texture(ma);
 +                      material_panel_layers(ma);
                        
 -                      mtex= ma->mtex[ ma->texact ];
 -                      if(mtex && mtex->tex) {
 -                              material_panel_map_input(ob, ma);
 -                              material_panel_map_to(ma);
 +                      ma= get_active_matlayer(ma);
 +                      if(ma) {
 +                              material_panel_ramps(ma);
 +                              material_panel_shading(ma);
 +                              
 +                              if (G.scene->r.renderer==R_INTERN)
 +                                      material_panel_tramir(ma);
 +                              else {
 +                                      if(ma->YF_ar==0.f) {
 +                                              ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
 +                                              ma->YF_dscale = 1;
 +                                      }
 +                                      material_panel_tramir_yafray(ma);
 +                              }
 +                              
 +                              material_panel_texture(ma);
 +                              
 +                              mtex= ma->mtex[ ma->texact ];
 +                              if(mtex && mtex->tex) {
 +                                      material_panel_map_input(ob, ma);
 +                                      material_panel_map_to(ma);
 +                              }
                        }
                }
        }
@@@ -3723,7 -3405,6 +3727,7 @@@ void texture_panels(
        if(G.buts->texfrom==0) {
                if(ob) {
                        ma= give_current_material(ob, ob->actcol);
 +                      ma= get_active_matlayer(ma);
                        if(ma) mtex= ma->mtex[ ma->texact ];
                }
        }
@@@ -3847,8 -3528,8 +3851,8 @@@ void clever_numbuts_buts(
                break;
        case TAB_SHADING_MAT:
  
 -              ma= G.buts->lockpoin;
 -
 +              ma= get_active_matlayer(G.buts->lockpoin);
 +              
                /* Build a hex value */
                if (ma){
                        sprintf(hexrgb, "%02X%02X%02X", (int)(ma->r*255), (int)(ma->g*255), (int)(ma->b*255));
index a8f90b95ed845d31ae0158601a250267bffd30c7,6316d6d6bac4786fd4ad00af7eeee0aabb5efb1b..a3f068dc5a5f47222d00e0e3912adb8dffa3df6b
@@@ -1,12 -1,20 +1,12 @@@
  /**
 - * header_oops.c oct-2003
 - *
 - * Functions to draw the "OOPS Schematic" window header
 - * and handle user events sent to it.
 - * 
   * $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
   * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
   * All rights reserved.
   *
 - * The Original Code is: all of this file.
 + * The Original Code is: not all of this file anymore.
   *
 - * Contributor(s): none yet.
 + * Contributor(s): Blender Foundation.
   *
 - * ***** END GPL/BL DUAL LICENSE BLOCK *****
 + * ***** END GPL LICENSE BLOCK *****
   */
  
  #include <stdlib.h>
@@@ -63,6 -71,9 +63,9 @@@
  
  #include "BKE_depsgraph.h"
  
+ #include "BPY_extern.h"
+ #include "BPY_menus.h"
  static int viewmovetemp = 0;
  
  void do_oops_buttons(short event)
@@@ -74,7 -85,7 +77,7 @@@
        switch(event) {
        case B_OOPSHOME:
                init_v2d_oops(curarea, curarea->spacedata.first);       // forces min/max to be reset
-               boundbox_oops();
+               boundbox_oops(0);
                G.v2d->cur= G.v2d->tot;
                dx= 0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin);
                dy= 0.15*(G.v2d->cur.ymax-G.v2d->cur.ymin);
                test_view2d(G.v2d, curarea->winx, curarea->winy);
                scrarea_queue_winredraw(curarea);
                break;
+       
+       case B_OOPSVIEWSEL:
+               init_v2d_oops(curarea, curarea->spacedata.first);       // forces min/max to be reset
+               boundbox_oops(1);
+               G.v2d->cur= G.v2d->tot;
+               dx= 0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin);
+               dy= 0.15*(G.v2d->cur.ymax-G.v2d->cur.ymin);
+               G.v2d->cur.xmin-= dx;
+               G.v2d->cur.xmax+= dx;
+               G.v2d->cur.ymin-= dy;
+               G.v2d->cur.ymax+= dy;           
+               test_view2d(G.v2d, curarea->winx, curarea->winy);
+               scrarea_queue_winredraw(curarea);
+               break;
+       
        case B_NEWOOPS:
                scrarea_queue_winredraw(curarea);
                scrarea_queue_headredraw(curarea);
@@@ -107,10 -132,13 +124,13 @@@ static void do_oops_viewmenu(void *arg
      case 2: /* View All */
                do_oops_buttons(B_OOPSHOME);
                break;
-       case 3: /* Maximize Window */
+     case 3: /* View All */
+               do_oops_buttons(B_OOPSVIEWSEL);
+               break;
+       case 4: /* Maximize Window */
                /* using event B_FULL */
                break;
-       case 4: /* show outliner */
+       case 5: /* show outliner */
                {
                        SpaceOops *soops= curarea->spacedata.first;
                        if(soops->type==SO_OOPS || soops->type==SO_DEPSGRAPH) soops->type= SO_OUTLINER;
                        scrarea_queue_winredraw(curarea);
                }
                break;
-       case 5:
+       case 6:
                outliner_toggle_visible(curarea);
                break;
-       case 6:
+       case 7:
                outliner_show_hierarchy(curarea);
                break;
-       case 7:
+       case 8:
                outliner_show_active(curarea);
                break;
-       case 8:
+       case 9:
                outliner_one_level(curarea, 1);
                break;
-       case 9:
+       case 10:
                outliner_one_level(curarea, -1);
                break;
  #ifdef SHOWDEPGRAPH
-       case 10:
+       case 11:
                // show deps
                {
                        SpaceOops *soops= curarea->spacedata.first;
@@@ -164,9 -192,9 +184,9 @@@ static uiBlock *oops_viewmenu(void *arg
        uiBlockSetButmFunc(block, do_oops_viewmenu, NULL);
        
        if(soops->type==SO_OOPS) {
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Outliner", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Outliner", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
  #ifdef SHOWDEPGRAPH
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Dependancies", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Dependancies", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
  #endif
                uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");  
  
                uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");  
  
                uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Selected|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
        }
  #ifdef SHOWDEPGRAPH
        else if(soops->type==SO_DEPSGRAPH) {
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Outliner", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Oops Schematic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Outliner", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Oops Schematic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
        }
  #endif
        else {
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Oops Schematic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Oops Schematic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
                
                uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
                
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Expand One Level|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Collapse One Level|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Expand One Level|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Collapse One Level|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
                
                uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");  
  
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show/Hide All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hierarchy|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
-               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Active|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show/Hide All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hierarchy|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Active|NumPad .", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
        }
        
        uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");  
-       if(!curarea->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
-       else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+       if(!curarea->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+       else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
        
        if(curarea->headertype==HEADERTOP) {
                uiBlockSetDirection(block, UI_DOWN);
@@@ -306,6 -335,7 +327,7 @@@ static uiBlock *oops_blockmenu(void *ar
  }
  
  
  void oops_buttons(void)
  {     
        SpaceOops *soops;
                        xmax= GetButStringLength("Block");
                        uiDefPulldownBut(block, oops_blockmenu, NULL, "Block", xco, -2, xmax-3, 24, "");
                        xco+= xmax;
+                       
                }
        }
  
        } 
  #endif
        else {
 -              uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Same Types %x5|Selected %x3|Active %x4",  xco, 0, 100, 20,  &soops->outlinevis, 0, 0, 0, 0, "");
 +              uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4",       xco, 0, 100, 20,  &soops->outlinevis, 0, 0, 0, 0, "");
        }
        
        /* always do as last */
index 4316c4837cf927c357795f03dd2f54f4336b8f71,d7cc7bdc478dd1aa3feec67e2be3f2fa5ae94a59..b659362d60a4a03b3c0dfb632dec8c2994cc1320
@@@ -39,7 -39,6 +39,7 @@@
  #include "DNA_camera_types.h"
  #include "DNA_image_types.h"
  #include "DNA_ipo_types.h"
 +#include "DNA_group_types.h"
  #include "DNA_key_types.h"
  #include "DNA_lamp_types.h"
  #include "DNA_material_types.h"
  #include "BKE_constraint.h"
  #include "BKE_depsgraph.h"
  #include "BKE_global.h"
 +#include "BKE_group.h"
  #include "BKE_library.h"
  #include "BKE_main.h"
  #include "BKE_material.h"
  #include "BKE_modifier.h"
  #include "BKE_screen.h"
 +#include "BKE_scene.h"
  #include "BKE_utildefines.h"
  
  #include "BIF_butspace.h"
  
  #define TS_CHUNK      128
  
 -#define TREESTORE(a) soops->treestore->data+(a)->store_index
 +#define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL)
  
  /* ******************** PERSISTANT DATA ***************** */
  
@@@ -512,13 -509,13 +512,13 @@@ static TreeElement *outliner_add_elemen
                                                te->name= md->name;
  
                                                if (md->type==eModifierType_Lattice) {
 -                                                      outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
 +                                                      outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Curve) {
 -                                                      outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
 +                                                      outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Armature) {
 -                                                      outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
 +                                                      outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Hook) {
 -                                                      outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
 +                                                      outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                }
                                        }
                                }
                                                outliner_add_element(soops, &tenla->subtree, ob->scriptlink.scripts[a], te, 0, 0);
                                        }
                                }
 +                              
 +                              if(ob->dup_group)
 +                                      outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
 +                              
                                if(ob->nlastrips.first) {
                                        bActionStrip *strip;
                                        TreeElement *ten;
@@@ -775,25 -768,6 +775,25 @@@ static void outliner_build_tree(SpaceOo
                }
                outliner_make_hierarchy(soops, &soops->tree);
        }
 +      else if(soops->outlinevis == SO_GROUPS) {
 +              Group *group;
 +              GroupObject *go;
 +              
 +              for(group= G.main->group.first; group; group= group->id.next) {
 +                      if(group->id.us) {
 +                              te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
 +                              tselem= TREESTORE(te);
 +                              
 +                              for(go= group->gobject.first; go; go= go->next) {
 +                                      ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
 +                                      ten->directdata= NULL;
 +                              }
 +                              outliner_make_hierarchy(soops, &te->subtree);
 +                              /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
 +                              for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL;
 +                      }
 +              }
 +      }
        else if(soops->outlinevis == SO_SAME_TYPE) {
                Object *ob= OBACT;
                if(ob) {
@@@ -1432,7 -1406,7 +1432,7 @@@ static int tree_element_type_active(Spa
                        return tree_element_active_ebone(te, tselem, set);
                case TSE_MODIFIER:
                        return tree_element_active_modifier(te, tselem, set);
 -              case TSE_MODIFIER_OB:
 +              case TSE_LINKED_OB:
                        if(set) tree_element_active_object(soops, te);
                        else if(tselem->id==(ID *)OBACT) return 1;
                        break;
@@@ -1482,8 -1456,6 +1482,8 @@@ static int do_outliner_mouse_event(Spac
                        if(G.qual & LR_CTRLKEY) {
                                if(ELEM5(tselem->type, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, TSE_SCRIPT_BASE)) 
                                        error("Cannot edit builtin name");
 +                              else if(tselem->id->lib)
 +                                      error("Cannot edit Library Data");
                                else {
                                        tselem->flag |= TSE_TEXTBUT;
                                }
@@@ -1717,9 -1689,12 +1717,9 @@@ static void set_operation_types(SpaceOo
                                                
                                        case ID_ME: case ID_CU: case ID_MB: case ID_LT:
                                        case ID_LA: case ID_AR: case ID_CA:
 -                                              idlevel= -2;
 -                                              break;
 -                                              
                                        case ID_MA: case ID_TE: case ID_IP: case ID_IM:
                                        case ID_SO: case ID_KE: case ID_WO: case ID_AC:
 -                                      case ID_NLA: case ID_TXT:
 +                                      case ID_NLA: case ID_TXT: case ID_GR:
                                                if(idlevel==0) idlevel= idcode;
                                                else if(idlevel!=idcode) idlevel= -1;
                                                        break;
        }
  }
  
 -static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep)
 +static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
  {
        Material **matar=NULL;
        int a, totcol=0;
        }
  }
  
 -static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep)
 +static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
  {
        MTex **mtex= NULL;
        int a;
        }
  }
  
 +static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 +{
 +      Group *group= (Group *)tselem->id;
 +      
 +      if(tsep) {
 +              if( GS(tsep->id->name)==ID_OB) {
 +                      Object *ob= (Object *)tsep->id;
 +                      ob->dup_group= NULL;
 +                      group->id.us--;
 +              }
 +      }
 +      else {
 +              unlink_group(group);
 +              group->id.us= 0;
 +      }
 +}
 +
  static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, 
 -                                                                               void (*operation_cb)(TreeElement *, TreeStoreElem *))
 +                                                                               void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
  {
        TreeElement *te;
        TreeStoreElem *tselem;
                if(tselem->flag & TSE_SELECTED) {
                        if(tselem->type==0) {
                                TreeStoreElem *tsep= TREESTORE(te->parent);
 -                              operation_cb(te, tsep);
 +                              operation_cb(te, tsep, tselem);
                        }
                }
                if((tselem->flag & TSE_CLOSED)==0) {
  
  /* */
  
 -static void object_select_cb(TreeElement *te, TreeStoreElem *tselem)
 +static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
  {
        Base *base= (Base *)te->directdata;
        
 -      base->flag |= SELECT;
 -      base->object->flag |= SELECT;
 +      if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene);
 +      if(base) {
 +              base->flag |= SELECT;
 +              base->object->flag |= SELECT;
 +      }
  }
  
 -static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem)
 +static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
  {
        Base *base= (Base *)te->directdata;
        
 -      base->flag &= ~SELECT;
 -      base->object->flag &= ~SELECT;
 +      if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene);
 +      if(base) {
 +              base->flag &= ~SELECT;
 +              base->object->flag &= ~SELECT;
 +      }
  }
  
 -static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem)
 +static void object_delete_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
  {
        Base *base= (Base *)te->directdata;
        
 +      if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene);
        if(base) {
                // check also library later
                if(G.obedit==base->object) exit_editmode(2);
        }
  }
  
 +static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 +{
 +      if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
 +              tselem->id->lib= NULL;
 +              tselem->id->flag= LIB_LOCAL;
 +              new_id(0, tselem->id, 0);
 +      }
 +}
  
  static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, 
 -                                                                               void (*operation_cb)(TreeElement *, TreeStoreElem *))
 +                                                                               void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
  {
        TreeElement *te;
        TreeStoreElem *tselem;
                                Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
                                if(sce && G.scene != sce) set_scene(sce);
                                
 -                              operation_cb(te, tselem);
 +                              operation_cb(te, NULL, tselem);
                        }
                }
                if((tselem->flag & TSE_CLOSED)==0) {
@@@ -1988,7 -1931,7 +1988,7 @@@ void outliner_operation_menu(ScrArea *s
                //else pupmenu("Scene Operations%t|Delete");
        }
        else if(objectlevel) {
 -              short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4");
 +              short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4|Make Local%x5");
                if(event>0) {
                        char *str="";
                        
                                DAG_scene_sort(G.scene);
                                str= "Delete Objects";
                        }
 +                      else if(event==5) {
 +                              outliner_do_object_operation(soops, &soops->tree, id_local_cb);
 +                              str= "Localized Objects";
 +                      }
                        
                        countall();
                        
                        BIF_undo_push(str);
 -                      allqueue(REDRAWALL, 0); // yah... to be sure :)
 +                      allqueue(REDRAWALL, 0);
                }
        }
        else if(idlevel) {
                if(idlevel==-1 || datalevel) error("Mixed selection");
 -              else if(idlevel==-2) error("No operations available");
                else {
 -                      short event= pupmenu("Data Operations%t|Unlink");
 +                      short event= pupmenu("Data Operations%t|Unlink %x1|Make Local %x2");
                        
                        if(event==1) {
                                switch(idlevel) {
                                                allqueue(REDRAWBUTSSHADING, 1);
                                                BIF_undo_push("Unlink texture");
                                                break;
 +                                      case ID_GR:
 +                                              outliner_do_libdata_operation(soops, &soops->tree, unlink_group_cb);
 +                                              BIF_undo_push("Unlink group");
 +                                              break;
                                        default:
                                                error("Not yet...");
                                }
 -                              allqueue(REDRAWOOPS, 0);
 -                              allqueue(REDRAWBUTSALL, 0);
 -                              allqueue(REDRAWVIEW3D, 0);
 +                              allqueue(REDRAWALL, 0);
 +                      }
 +                      else if(event==2) {
 +                              outliner_do_libdata_operation(soops, &soops->tree, id_local_cb);
 +                              BIF_undo_push("Localized Data");
 +                              allqueue(REDRAWALL, 0); 
                        }
                }
        }
@@@ -2104,7 -2037,7 +2104,7 @@@ static void tselem_draw_icon(float x, f
                                BIF_draw_icon(x, y, ICON_CONSTRAINT); break;
                        case TSE_MODIFIER_BASE:
                                BIF_draw_icon(x, y, ICON_MODIFIER); break;
 -                      case TSE_MODIFIER_OB:
 +                      case TSE_LINKED_OB:
                                BIF_draw_icon(x, y, ICON_OBJECT); break;
                        case TSE_MODIFIER:
                        {
                                BIF_draw_icon(x, y, ICON_NLA); break;
                        case ID_TXT:
                                BIF_draw_icon(x, y, ICON_SCRIPT); break;
 +                      case ID_GR:
 +                              BIF_draw_icon(x, y, ICON_CIRCLE_DEHLT); break;
                }
        }
  }
@@@ -2292,7 -2223,7 +2292,7 @@@ static void outliner_draw_tree_element(
                if(active) {
                        uiSetRoundBox(15);
                        uiRoundBox( (float)startx+OL_H-1.5, (float)*starty+2.0, (float)startx+2*OL_H-4.0, (float)*starty+OL_H-1.0, OL_H/2.0-2.0);
 -                      glEnable(GL_BLEND);
 +                      glEnable(GL_BLEND);     /* roundbox disables it */
                        
                        te->flag |= TE_ACTIVE; // for lookup in display hierarchies
                }
                        // icons a bit higher
                tselem_draw_icon(startx+offsx, *starty+2, tselem, te);
                offsx+= OL_X;
 +              
 +              if(tselem->id->lib && tselem->type==0) {
 +                      glPixelTransferf(GL_ALPHA_SCALE, 0.5);
 +                      if(tselem->id->flag & LIB_INDIRECT)
 +                              BIF_draw_icon(startx+offsx, *starty+2, ICON_DATALIB);
 +                      else
 +                              BIF_draw_icon(startx+offsx, *starty+2, ICON_PARLIB);
 +                      glPixelTransferf(GL_ALPHA_SCALE, 1.0);
 +                      offsx+= OL_X;
 +              }               
                glDisable(GL_BLEND);
  
                /* name */
@@@ -2472,93 -2393,84 +2472,84 @@@ static void outliner_back(SpaceOops *so
        }
  }
  
- static void namebutton_cb(void *soopsp, void *oldnamep)
+ static void namebutton_cb(void *tep, void *oldnamep)
  {
-       SpaceOops *soops= soopsp;
+       SpaceOops *soops= curarea->spacedata.first;
        TreeStore *ts= soops->treestore;
-       TreeStoreElem *tselem;
-       int a;
+       TreeElement *te= tep;
        
-       if(ts) {
-               /* only one namebutton can exist */
-               for(a=0, tselem= ts->data; a<ts->usedelem; a++, tselem++) {
-                       if(tselem->flag & TSE_TEXTBUT) {
-                               if(tselem->type==0) {
-                                       test_idbutton(tselem->id->name+2);      // library.c, unique name and alpha sort
-                               }
-                               else {
-                                       TreeElement *te= outliner_find_tree_element(&soops->tree, a);
+       if(ts && te) {
+               TreeStoreElem *tselem= TREESTORE(te);
+               if(tselem->type==0) {
+                       test_idbutton(tselem->id->name+2);      // library.c, unique name and alpha sort
+               }
+               else {
+                       switch(tselem->type) {
+                       case TSE_DEFGROUP:
+                               unique_vertexgroup_name(te->directdata, (Object *)tselem->id); //       id = object
+                               break;
+                       case TSE_NLA_ACTION:
+                               test_idbutton(tselem->id->name+2);
+                               break;
+                       case TSE_EBONE:
+                               if(G.obedit && G.obedit->data==(ID *)tselem->id) {
+                                       EditBone *ebone= te->directdata;
+                                       char newname[32];
                                        
-                                       if(te) {
-                                               switch(tselem->type) {
-                                               case TSE_DEFGROUP:
-                                                       unique_vertexgroup_name(te->directdata, (Object *)tselem->id); //       id = object
-                                                       break;
-                                               case TSE_NLA_ACTION:
-                                                       test_idbutton(tselem->id->name+2);
-                                                       break;
-                                               case TSE_EBONE:
-                                                       if(G.obedit && G.obedit->data==(ID *)tselem->id) {
-                                                               EditBone *ebone= te->directdata;
-                                                               char newname[32];
-                                                               
-                                                               /* restore bone name */
-                                                               BLI_strncpy(newname, ebone->name, 32);
-                                                               BLI_strncpy(ebone->name, oldnamep, 32);
-                                                               armature_bone_rename(G.obedit->data, oldnamep, newname);
-                                                       }
-                                                       allqueue(REDRAWOOPS, 0);
-                                                       allqueue(REDRAWVIEW3D, 1);
-                                                       allqueue(REDRAWBUTSEDIT, 0);
-                                                       break;
+                                       /* restore bone name */
+                                       BLI_strncpy(newname, ebone->name, 32);
+                                       BLI_strncpy(ebone->name, oldnamep, 32);
+                                       armature_bone_rename(G.obedit->data, oldnamep, newname);
+                               }
+                               allqueue(REDRAWOOPS, 0);
+                               allqueue(REDRAWVIEW3D, 1);
+                               allqueue(REDRAWBUTSEDIT, 0);
+                               break;
  
-                                               case TSE_BONE:
-                                                       {
-                                                               Bone *bone= te->directdata;
-                                                               Object *ob;
-                                                               char newname[32];
-                                                               
-                                                               // always make current object active
-                                                               tree_element_active_object(soops, te);
-                                                               ob= OBACT;
-                                                               
-                                                               /* restore bone name */
-                                                               BLI_strncpy(newname, bone->name, 32);
-                                                               BLI_strncpy(bone->name, oldnamep, 32);
-                                                               armature_bone_rename(ob->data, oldnamep, newname);
-                                                       }
-                                                       allqueue(REDRAWOOPS, 0);
-                                                       allqueue(REDRAWVIEW3D, 1);
-                                                       allqueue(REDRAWBUTSEDIT, 0);
-                                                       break;
-                                               case TSE_POSE_CHANNEL:
-                                                       {
-                                                               bPoseChannel *pchan= te->directdata;
-                                                               Object *ob;
-                                                               char newname[32];
-                                                               
-                                                               // always make current object active
-                                                               tree_element_active_object(soops, te);
-                                                               ob= OBACT;
-                                                               
-                                                               /* restore bone name */
-                                                               BLI_strncpy(newname, pchan->name, 32);
-                                                               BLI_strncpy(pchan->name, oldnamep, 32);
-                                                               armature_bone_rename(ob->data, oldnamep, newname);
-                                                       }
-                                                       allqueue(REDRAWOOPS, 0);
-                                                       allqueue(REDRAWVIEW3D, 1);
-                                                       allqueue(REDRAWBUTSEDIT, 0);
-                                                       break;
-                                                       
-                                               }
-                                       }
+                       case TSE_BONE:
+                               {
+                                       Bone *bone= te->directdata;
+                                       Object *ob;
+                                       char newname[32];
+                                       
+                                       // always make current object active
+                                       tree_element_active_object(soops, te);
+                                       ob= OBACT;
+                                       
+                                       /* restore bone name */
+                                       BLI_strncpy(newname, bone->name, 32);
+                                       BLI_strncpy(bone->name, oldnamep, 32);
+                                       armature_bone_rename(ob->data, oldnamep, newname);
+                               }
+                               allqueue(REDRAWOOPS, 0);
+                               allqueue(REDRAWVIEW3D, 1);
+                               allqueue(REDRAWBUTSEDIT, 0);
+                               break;
+                       case TSE_POSE_CHANNEL:
+                               {
+                                       bPoseChannel *pchan= te->directdata;
+                                       Object *ob;
+                                       char newname[32];
+                                       
+                                       // always make current object active
+                                       tree_element_active_object(soops, te);
+                                       ob= OBACT;
+                                       
+                                       /* restore bone name */
+                                       BLI_strncpy(newname, pchan->name, 32);
+                                       BLI_strncpy(pchan->name, oldnamep, 32);
+                                       armature_bone_rename(ob->data, oldnamep, newname);
                                }
-                               tselem->flag &= ~TSE_TEXTBUT;
+                               allqueue(REDRAWOOPS, 0);
+                               allqueue(REDRAWVIEW3D, 1);
+                               allqueue(REDRAWBUTSEDIT, 0);
+                               break;
+                               
                        }
                }
-               scrarea_queue_redraw(curarea);
        }
+       scrarea_queue_redraw(curarea);
  }
  
  static void outliner_buttons(uiBlock *block, SpaceOops *soops, ListBase *lb)
                        if(dx<50) dx= 50;
                        
                        bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "",  te->xs+2*OL_X-4, te->ys, dx+10, OL_H-1, te->name, 1.0, (float)len-1, 0, 0, "");
-                       uiButSetFunc(bt, namebutton_cb, soops, NULL);
+                       uiButSetFunc(bt, namebutton_cb, te, NULL);
  
                        // signal for button to open
                        addqueue(curarea->win, BUT_ACTIVATE, OL_NAMEBUTTON);
index cfadcc44ec8a8d0d5ded352eb4b76ded4ba04fe2,b89be1ad43699b0cd8bca49b2ad60d2f880857ec..ee10006addc1352c83acf313c4146bfe63477b0c
@@@ -89,7 -89,6 +89,7 @@@
  #include "BIF_editarmature.h"
  #include "BIF_editconstraint.h"
  #include "BIF_editfont.h"
 +#include "BIF_editgroup.h"
  #include "BIF_editkey.h"
  #include "BIF_editlattice.h"
  #include "BIF_editmesh.h"
@@@ -578,10 -577,31 +578,10 @@@ static void select_parent(void) /* Make
        }
  }
  
 -
 -void select_group_menu(void)
 -{
 -      char *str;
 -      short nr;
 -
 -      /* make menu string */
 -      
 -      str= MEM_mallocN(160, "groupmenu");
 -      strcpy(str, "Select Grouped%t|Children%x1|"
 -                  "Immediate Children%x2|Parent%x3|"
 -                  "Objects on Shared Layers%x4");
 -
 -      /* here we go */
 -      
 -      nr= pupmenu(str);
 -      MEM_freeN(str);
 -      
 -      select_group(nr);
 -}
 -
 -void select_group(short nr)
 +void select_grouped(short nr)
  {
        Base *base;
 -
 +      
        if(nr==4) {
                base= FIRSTBASE;
                while(base) {
        allqueue(REDRAWIPO, 0);
  }
  
 +static void select_grouped_menu(void)
 +{
 +      char *str;
 +      short nr;
 +
 +      /* make menu string */
 +      
 +      str= MEM_mallocN(160, "groupmenu");
 +      strcpy(str, "Select Grouped%t|Children%x1|"
 +                  "Immediate Children%x2|Parent%x3|"
 +                  "Objects on Shared Layers%x4");
 +
 +      /* here we go */
 +      
 +      nr= pupmenu(str);
 +      MEM_freeN(str);
 +      
 +      select_grouped(nr);
 +}
 +
 +
  static unsigned short convert_for_nonumpad(unsigned short event)
  {
        if (event>=ZEROKEY && event<=NINEKEY) {
@@@ -1263,9 -1262,10 +1263,9 @@@ static void winqreadview3dspace(ScrAre
                                
                                break;
                        case GKEY:
 -                              /* RMGRP if(G.qual & LR_CTRLKEY) add_selected_to_group();
 -                              else if(G.qual & LR_ALTKEY) rem_selected_from_group(); */
 -                              if((G.qual==LR_SHIFTKEY))
 -                                      select_group_menu();
 +                              if(G.qual & LR_CTRLKEY) group_operation_with_menu();
 +                              else if((G.qual==LR_SHIFTKEY))
 +                                      select_grouped_menu();
                                else if(G.qual==LR_ALTKEY) {
                                        if(okee("Clear location")) {
                                                clear_object('g');
                                        mirrormenu();
                                }
                                else if(G.qual==0) {
 -                                   movetolayer();
 +                                      if(ob && (ob->flag & OB_POSEMODE))
 +                                              pose_movetolayer();
 +                                      else
 +                                              movetolayer();
                                }
                                break;
                        case NKEY:
@@@ -3870,7 -3867,8 +3870,7 @@@ static void winqreadimagespace(ScrArea 
                                        sample_vpaint();
                                break;
                        case AKEY:
 -                              if((G.qual==0))
 -                                      select_swap_tface_uv();
 +                              select_swap_tface_uv();
                                break;
                        case BKEY:
                                if(G.qual==LR_SHIFTKEY)
                                        stitch_uv_tface(0);
                                else if(G.qual==LR_SHIFTKEY)
                                        stitch_uv_tface(1);
 +                              else if(G.qual==LR_CTRLKEY)
 +                                      minimize_stretch_tface_uv();
                                break;
                        case WKEY:
                                weld_align_menu_tface_uv();
@@@ -4146,6 -4142,11 +4146,11 @@@ static void winqreadoopsspace(ScrArea *
                        if((G.qual==0))
                                do_oops_buttons(B_OOPSHOME);
                        break;
+               
+               case PADPERIOD:
+                       if((G.qual==0))
+                               do_oops_buttons(B_OOPSVIEWSEL);
+                       break;
                        
                case AKEY:
                        if((G.qual==0)) {
index bb8e433251b109426571d584fb700691a5a23be3,a99355359f17a20c574d1710587563896aad7b21..3e67eb1ca1f6a0cd7f1918c0158952637b413c13
@@@ -425,6 -425,8 +425,8 @@@ void persptoetsen(unsigned short event
                                if(((G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) || (G.qual & LR_SHIFTKEY)) {
                                        void setcameratoview3d(void);   // view.c
                                        setcameratoview3d();
+                                       DAG_object_flush_update(G.scene, G.scene->camera, OB_RECALC_OB);
+                                       allqueue(REDRAWVIEW3D, 0);
                                }                               
                        }
                }
@@@ -981,8 -983,7 +983,8 @@@ int blenderqread(unsigned short event, 
                                                screen_swapbuffers();
                                        }
                                        else if(event==3) {
 -                                              BKE_write_undo("10 timer");
 +                                              BIF_undo();
 +                                              BIF_redo();
                                        }
                                }
                        
                                
                                if(event==1) sprintf(tmpstr, "draw %%t|%d ms", time);
                                if(event==2) sprintf(tmpstr, "d+sw %%t|%d ms", time);
 -                              if(event==3) sprintf(tmpstr, "displist %%t|%d ms", time);
 -                              if(event==4) sprintf(tmpstr, "undo %%t|%d ms", time);
 +                              if(event==3) sprintf(tmpstr, "undo %%t|%d ms", time);
                        
                                waitcursor(0);
                                pupmenu(tmpstr);