Revision: 37936
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=37936
Author:   aligorith
Date:     2011-06-29 04:34:20 +0000 (Wed, 29 Jun 2011)
Log Message:
-----------
Actions can now be made single-user from the Outliner

* Use the same method as from unlinking actions to do this.
* Split off the make single-user code used for the ID-browser into a
function in blenkernel which can be used elsewhere. Getting materials
to also work using this method proved to be a bit too tricky (due to
the whole messy ob vs obdata situation), so I haven't done that.

Modified Paths:
--------------
    branches/soc-2011-pepper/source/blender/blenkernel/BKE_library.h
    branches/soc-2011-pepper/source/blender/blenkernel/intern/action.c
    branches/soc-2011-pepper/source/blender/blenkernel/intern/library.c
    
branches/soc-2011-pepper/source/blender/editors/interface/interface_templates.c
    branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c

Modified: branches/soc-2011-pepper/source/blender/blenkernel/BKE_library.h
===================================================================
--- branches/soc-2011-pepper/source/blender/blenkernel/BKE_library.h    
2011-06-29 03:02:20 UTC (rev 37935)
+++ branches/soc-2011-pepper/source/blender/blenkernel/BKE_library.h    
2011-06-29 04:34:20 UTC (rev 37936)
@@ -44,6 +44,8 @@
 struct Library;
 struct wmWindowManager;
 struct bContext;
+struct PointerRNA;
+struct PropertyRNA;
 
 void *alloc_libblock(struct ListBase *lb, short type, const char *name);
 void *copy_libblock(void *rt);
@@ -53,6 +55,7 @@
 void id_us_plus(struct ID *id);
 void id_us_min(struct ID *id);
 int id_make_local(struct ID *id, int test);
+int id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, 
struct PropertyRNA *prop);
 int id_copy(struct ID *id, struct ID **newid, int test);
 int id_unlink(struct ID *id, int test);
 

Modified: branches/soc-2011-pepper/source/blender/blenkernel/intern/action.c
===================================================================
--- branches/soc-2011-pepper/source/blender/blenkernel/intern/action.c  
2011-06-29 03:02:20 UTC (rev 37935)
+++ branches/soc-2011-pepper/source/blender/blenkernel/intern/action.c  
2011-06-29 04:34:20 UTC (rev 37936)
@@ -89,60 +89,80 @@
        return act;
 }      
 
+/* .................................. */
+
+/* temp data for make_local_action */
+typedef struct tMakeLocalActionContext {
+       bAction *act;    /* original action */
+       bAction *actn;   /* new action */
+       
+       int lib;         /* some action users were libraries */
+       int local;       /* some action users were not libraries */
+} tMakeLocalActionContext;
+
+/* helper function for make_local_action() - local/lib init step */
+static void make_localact_init_cb(ID *id, AnimData *adt, void *mlac_ptr)
+{
+       tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr;
+       
+       if (adt->action == mlac->act) {
+               if (id->lib) 
+                       mlac->lib = 1;
+               else 
+                       mlac->local = 1;
+       }
+}
+
+/* helper function for make_local_action() - change references */
+static void make_localact_apply_cb(ID *id, AnimData *adt, void *mlac_ptr)
+{
+       tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr;
+       
+       if (adt->action == mlac->act) {
+               if (id->lib==0) {
+                       adt->action = mlac->actn;
+                       
+                       id_us_plus(&mlac->actn->id);
+                       id_us_min(&mlac->act->id);
+               }
+       }
+}
+
 // does copy_fcurve...
 void make_local_action(bAction *act)
 {
-       // Object *ob;
+       tMakeLocalActionContext mlac = {act, NULL, 0, 0};
        Main *bmain= G.main;
-       bAction *actn;
-       int local=0, lib=0;
        
-       if (act->id.lib==NULL) return;
-       if (act->id.us==1) {
+       if (act->id.lib==NULL) 
+               return;
+       
+       // XXX: double-check this; it used to be just single-user check, but 
that was when fake-users were still default
+       if ((act->id.flag & LIB_FAKEUSER) && (act->id.us<=1)) {
                act->id.lib= NULL;
                act->id.flag= LIB_LOCAL;
                new_id(&bmain->action, (ID *)act, NULL);
                return;
        }
        
-#if 0  // XXX old animation system
-       ob= G.main->object.first;
-       while(ob) {
-               if(ob->action==act) {
-                       if(ob->id.lib) lib= 1;
-                       else local= 1;
-               }
-               ob= ob->id.next;
-       }
-#endif
+       BKE_animdata_main_cb(bmain, make_localact_init_cb, &mlac);
        
-       if(local && lib==0) {
+       if (mlac.local && mlac.lib==0) {
                act->id.lib= NULL;
                act->id.flag= LIB_LOCAL;
                //make_local_action_channels(act);
                new_id(&bmain->action, (ID *)act, NULL);
        }
-       else if(local && lib) {
-               actn= copy_action(act);
-               actn->id.us= 0;
+       else if (mlac.local && mlac.lib) {
+               mlac.actn= copy_action(act);
+               mlac.actn->id.us= 0;
                
-#if 0  // XXX old animation system
-               ob= G.main->object.first;
-               while(ob) {
-                       if(ob->action==act) {
-                               
-                               if(ob->id.lib==0) {
-                                       ob->action = actn;
-                                       actn->id.us++;
-                                       act->id.us--;
-                               }
-                       }
-                       ob= ob->id.next;
-               }
-#endif // XXX old animation system
+               BKE_animdata_main_cb(bmain, make_localact_apply_cb, &mlac);
        }
 }
 
+/* .................................. */
+
 void free_action (bAction *act)
 {
        /* sanity check */
@@ -161,6 +181,8 @@
                BLI_freelistN(&act->markers);
 }
 
+/* .................................. */
+
 bAction *copy_action (bAction *src)
 {
        bAction *dst = NULL;

Modified: branches/soc-2011-pepper/source/blender/blenkernel/intern/library.c
===================================================================
--- branches/soc-2011-pepper/source/blender/blenkernel/intern/library.c 
2011-06-29 03:02:20 UTC (rev 37935)
+++ branches/soc-2011-pepper/source/blender/blenkernel/intern/library.c 
2011-06-29 04:34:20 UTC (rev 37936)
@@ -368,6 +368,34 @@
        return 0;
 }
 
+int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
+{
+       ID *newid = NULL;
+       PointerRNA idptr;
+       
+       if (id) {
+               /* if property isn't editable, we're going to have an extra 
block hanging around until we save */
+               if (RNA_property_editable(ptr, prop)) {
+                       if (id_copy(id, &newid, 0) && newid) {
+                               /* copy animation actions too */
+                               BKE_copy_animdata_id_action(id);
+                               /* us is 1 by convention, but 
RNA_property_pointer_set
+                                  will also incremement it, so set it to zero 
*/
+                               newid->us= 0;
+                               
+                               /* assign copy */
+                               RNA_id_pointer_create(newid, &idptr);
+                               RNA_property_pointer_set(ptr, prop, idptr);
+                               RNA_property_update(C, ptr, prop);
+                               
+                               return 1;
+                       }
+               }
+       }
+       
+       return 0;
+}
+
 ListBase *which_libbase(Main *mainlib, short type)
 {
        switch( type ) {

Modified: 
branches/soc-2011-pepper/source/blender/editors/interface/interface_templates.c
===================================================================
--- 
branches/soc-2011-pepper/source/blender/editors/interface/interface_templates.c 
    2011-06-29 03:02:20 UTC (rev 37935)
+++ 
branches/soc-2011-pepper/source/blender/editors/interface/interface_templates.c 
    2011-06-29 04:34:20 UTC (rev 37936)
@@ -234,7 +234,7 @@
 {
        TemplateID *template= (TemplateID*)arg_litem;
        PointerRNA idptr= RNA_property_pointer_get(&template->ptr, 
template->prop);
-       ID *id= idptr.data, *newid;
+       ID *id= idptr.data;
        int event= GET_INT_FROM_POINTER(arg_event);
        
        switch(event) {
@@ -273,21 +273,8 @@
                        }
                        break;
                case UI_ID_ALONE:
-                       if(id) {
-                               /* make copy */
-                               if(id_copy(id, &newid, 0) && newid) {
-                                       /* copy animation actions too */
-                                       BKE_copy_animdata_id_action(id);
-                                       /* us is 1 by convention, but 
RNA_property_pointer_set
-                                          will also incremement it, so set it 
to zero */
-                                       newid->us= 0;
-
-                                       /* assign copy */
-                                       RNA_id_pointer_create(newid, &idptr);
-                                       
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
-                                       RNA_property_update(C, &template->ptr, 
template->prop);
-                               }
-                       }
+                       if(id) 
+                               id_single_user(C, id, &template->ptr, 
template->prop);
                        break;
 #if 0
                case UI_ID_AUTO_NAME:

Modified: 
branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c
===================================================================
--- branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c   
2011-06-29 03:02:20 UTC (rev 37935)
+++ branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c   
2011-06-29 04:34:20 UTC (rev 37936)
@@ -3340,6 +3340,23 @@
        }
 }
 
+
+static void singleuser_action_cb(bContext *C, Scene *UNUSED(scene), 
TreeElement *UNUSED(te), TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+       ID *id = tselem->id;
+       
+       if (id) {
+               IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id;
+               PointerRNA ptr = {{0}};
+               PropertyRNA *prop;
+               
+               RNA_pointer_create(&iat->id, &RNA_AnimData, iat->adt, &ptr);
+               prop = RNA_struct_find_property(&ptr, "action");
+               
+               id_single_user(C, id, &ptr, prop);
+       }
+}
+
 static void group_linkobs2scene_cb(bContext *UNUSED(C), Scene *scene, 
TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
 {
        Group *group= (Group *)tselem->id;
@@ -3634,10 +3651,18 @@
 
 /* **************************************** */
 
+typedef enum eOutlinerIdOpTypes {
+       OUTLINER_IDOP_INVALID = 0,
+       OUTLINER_IDOP_UNLINK,
+       OUTLINER_IDOP_LOCAL,
+       OUTLINER_IDOP_SINGLE
+} eOutlinerIdOpTypes;
+
 // TODO: implement support for changing the ID-block used
 static EnumPropertyItem prop_id_op_types[] = {
-       {1, "UNLINK", 0, "Unlink", ""},
-       {2, "LOCAL", 0, "Make Local", ""},
+       {OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""},
+       {OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
+       {OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -3646,7 +3671,7 @@
        Scene *scene= CTX_data_scene(C);
        SpaceOops *soops= CTX_wm_space_outliner(C);
        int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
-       int event;
+       eOutlinerIdOpTypes event;
        
        /* check for invalid states */
        if (soops == NULL)
@@ -3656,34 +3681,66 @@
        
        event= RNA_enum_get(op->ptr, "type");
        
-       if(event==1) {
-               switch(idlevel) {
-                       case ID_AC:
-                               outliner_do_libdata_operation(C, scene, soops, 
&soops->tree, unlink_action_cb);
-                               
-                               WM_event_add_notifier(C, 
NC_ANIMATION|ND_NLA_ACTCHANGE, NULL);
-                               ED_undo_push(C, "Unlink action");
-                               break;
-                       case ID_MA:
-                               outliner_do_libdata_operation(C, scene, soops, 
&soops->tree, unlink_material_cb);
-                               
-                               WM_event_add_notifier(C, 
NC_OBJECT|ND_OB_SHADING, NULL);
-                               ED_undo_push(C, "Unlink material");
-                               break;
-                       case ID_TE:
-                               outliner_do_libdata_operation(C, scene, soops, 
&soops->tree, unlink_texture_cb);
-                               
-                               WM_event_add_notifier(C, 
NC_OBJECT|ND_OB_SHADING, NULL);
-                               ED_undo_push(C, "Unlink texture");
-                               break;
-                       default:
-                               BKE_report(op->reports, RPT_WARNING, "Not Yet");
+       switch (event) {
+               case OUTLINER_IDOP_UNLINK:
+               {
+                       /* unlink datablock from its parent */
+                       switch (idlevel) {
+                               case ID_AC:
+                                       outliner_do_libdata_operation(C, scene, 
soops, &soops->tree, unlink_action_cb);
+                                       
+                                       WM_event_add_notifier(C, 
NC_ANIMATION|ND_NLA_ACTCHANGE, NULL);
+                                       ED_undo_push(C, "Unlink action");
+                                       break;
+                               case ID_MA:
+                                       outliner_do_libdata_operation(C, scene, 
soops, &soops->tree, unlink_material_cb);
+                                       
+                                       WM_event_add_notifier(C, 
NC_OBJECT|ND_OB_SHADING, NULL);
+                                       ED_undo_push(C, "Unlink material");
+                                       break;
+                               case ID_TE:
+                                       outliner_do_libdata_operation(C, scene, 
soops, &soops->tree, unlink_texture_cb);
+                                       
+                                       WM_event_add_notifier(C, 
NC_OBJECT|ND_OB_SHADING, NULL);
+                                       ED_undo_push(C, "Unlink texture");
+                                       break;
+                               default:
+                                       BKE_report(op->reports, RPT_WARNING, 
"Not Yet");
+                                       break;
+                       }
                }
+                       break;
+                       
+               case OUTLINER_IDOP_LOCAL:
+               {
+                       /* make local */

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to