Saturday merger of bf-blender in orange branch.
[blender.git] / source / blender / src / outliner.c
index d7cc7bdc478dd1aa3feec67e2be3f2fa5ae94a59..b659362d60a4a03b3c0dfb632dec8c2994cc1320 100644 (file)
@@ -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 ***************** */
 
@@ -509,13 +512,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                                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);
                                                }
                                        }
                                }
@@ -541,6 +544,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                                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;
@@ -768,6 +775,25 @@ static void outliner_build_tree(SpaceOops *soops)
                }
                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) {
@@ -1406,7 +1432,7 @@ static int tree_element_type_active(SpaceOops *soops, TreeElement *te, TreeStore
                        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;
@@ -1456,6 +1482,8 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
                        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;
                                }
@@ -1689,12 +1717,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
                                                
                                        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;
@@ -1705,7 +1730,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
        }
 }
 
-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;
@@ -1739,7 +1764,7 @@ static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep)
        }
 }
 
-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;
@@ -1768,8 +1793,25 @@ static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep)
        }
 }
 
+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;
@@ -1779,7 +1821,7 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
                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) {
@@ -1790,26 +1832,33 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
 
 /* */
 
-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);
@@ -1825,9 +1874,17 @@ static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem)
        }
 }
 
+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;
@@ -1840,7 +1897,7 @@ static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb,
                                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) {
@@ -1931,7 +1988,7 @@ void outliner_operation_menu(ScrArea *sa)
                //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="";
                        
@@ -1951,18 +2008,21 @@ void outliner_operation_menu(ScrArea *sa)
                                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) {
@@ -1976,12 +2036,19 @@ void outliner_operation_menu(ScrArea *sa)
                                                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); 
                        }
                }
        }
@@ -2037,7 +2104,7 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
                                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:
                        {
@@ -2121,6 +2188,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
                                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;
                }
        }
 }
@@ -2223,7 +2292,7 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
                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
                }
@@ -2249,6 +2318,16 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
                        // 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 */