2.5
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 4 Sep 2009 21:02:43 +0000 (21:02 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 4 Sep 2009 21:02:43 +0000 (21:02 +0000)
Make local and make single user are back for ID template.

Internally these calls got unified, id_make_local and
id_copy are now used to do these operations for all types
that support it. Also reveals that for some ID types the
implementation is still missing.

Further, some small changes:

* unlink_text is now in blenkernel.
* copy_group was implemented.
* ID template now has an open operator again.
* fix preview to not change material reference count,
  even if temporary it shows up with threaded preview.
* id_unlink unifies unlink for text, object and group.

20 files changed:
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_group.h
source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/BKE_sca.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_text.h
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/sca.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/text.c
source/blender/editors/gpencil/gpencil_buttons.c
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_edit.c
source/blender/editors/preview/previewrender.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_text/text_intern.h
source/blender/editors/space_text/text_ops.c
source/blender/makesrna/intern/rna_ui_api.c

index 0595134f5c9b0c94c84d1d201f77ac939e7f94de..1cbb2331782f223aa5193bd2dc4ff9f94bfdf67b 100644 (file)
@@ -74,7 +74,6 @@ struct bArmature *add_armature(char *name);
 struct bArmature *get_armature(struct Object *ob);
 void free_boneChildren(struct Bone *bone);
 void free_bones (struct bArmature *arm);
-void unlink_armature(struct bArmature *arm);
 void free_armature(struct bArmature *arm);
 void make_local_armature(struct bArmature *arm);
 struct bArmature *copy_armature(struct bArmature *arm);
index 35084aabadf5b1d0e2f6bc4f3a7b8c8e0d950989..b66ddf13527a63beea134ecaee206e68973cccb0 100644 (file)
@@ -41,6 +41,7 @@ void          free_group_object(struct GroupObject *go);
 void           free_group(struct Group *group);
 void           unlink_group(struct Group *group);
 struct Group *add_group(char *name);
+struct Group *copy_group(struct Group *group);
 void           add_to_group(struct Group *group, struct Object *ob);
 int                    rem_from_group(struct Group *group, struct Object *ob);
 struct Group *find_group(struct Object *ob, struct Group *group);
index 4e7db115168ddcf72e10a93f5e8a79cfb65e64c3..54722dac910c237f5ffecb3be13454e77a1fd053 100644 (file)
@@ -46,6 +46,9 @@ void *copy_libblock(void *rt);
 void id_lib_extern(struct ID *id);
 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_copy(struct ID *id, struct ID **newid, int test);
+int id_unlink(struct ID *id, int test);
 
 int check_for_dupid(struct ListBase *lb, struct ID *id, char *name);
 int new_id(struct ListBase *lb, struct ID *id, const char *name);
index 22c4f39148a3fe17e6af219d4a24fe19061e3fe4..1b8e61f136f8e10d3cc7fe34428f8ff39458bd2f 100644 (file)
@@ -47,7 +47,6 @@ void unlink_actuators(struct ListBase *lb);
 void free_actuator(struct bActuator *act);
 void free_actuators(struct ListBase *lb);
 
-void free_text_controllers(struct Text *txt);
 void free_sensor(struct bSensor *sens);
 void free_sensors(struct ListBase *lb);
 struct bSensor *copy_sensor(struct bSensor *sens);
index 12a13a2b50c0ff9d6f1746ea2d627a375089b53d..686fc265de0bd41462799c0a478aedc9f3b1d317 100644 (file)
@@ -84,7 +84,5 @@ int get_render_child_particle_number(struct RenderData *r, int num);
 int get_render_shadow_samples(struct RenderData *r, int samples);
 float get_render_aosss_error(struct RenderData *r, float error);
 
-void free_dome_warp_text(struct Text *txt);
-
 #endif
 
index d288c0b651675c2f244ab19c3f0bc28d9102dd28..bd14053d121482b980d6a6ea475387cf50d02751 100644 (file)
@@ -35,6 +35,7 @@
 extern "C" {
 #endif
 
+struct Main;
 struct Text;
 struct TextLine;
 struct SpaceText;
@@ -46,6 +47,7 @@ struct Text*  add_empty_text  (char *name);
 int                reopen_text         (struct Text *text);
 struct Text*   add_text                (char *file, const char *relpath); 
 struct Text*   copy_text               (struct Text *ta);
+void                   unlink_text             (struct Main *bmain, struct Text *text);
 
 char*  txt_to_buf                      (struct Text *text);
 void   txt_clean_text          (struct Text *text);
index 6fffbd794ef75b5dc4824e9a9c3c8bd1275133e6..6bb47bc0f0f6bd31d11780951e2946fc2e6006fa 100644 (file)
@@ -142,6 +142,16 @@ Group *add_group(char *name)
        return group;
 }
 
+Group *copy_group(Group *group)
+{
+       Group *groupn;
+
+       groupn= MEM_dupallocN(group);
+       BLI_duplicatelist(&groupn->gobject, &group->gobject);
+
+       return groupn;
+}
+
 /* external */
 void add_to_group(Group *group, Object *ob)
 {
index 3c8bf9200f82497e8703d8598c0bf90fe4e30aaa..f15552ab40c369ac7721ad44cb399c4f77c12897 100644 (file)
 
 #define MAX_IDPUP              60      /* was 24 */
 
+/* GS reads the memory pointed at in a specific ordering. 
+   only use this definition, makes little and big endian systems
+   work fine, in conjunction with MAKE_ID */
+
+/* from blendef: */
+#define GS(a)  (*((short *)(a)))
+
 /* ************* general ************************ */
 
 void id_lib_extern(ID *id)
@@ -148,6 +155,217 @@ void id_us_min(ID *id)
                id->us--;
 }
 
+int id_make_local(ID *id, int test)
+{
+       if(id->flag & LIB_INDIRECT)
+               return 0;
+
+       switch(GS(id->name)) {
+               case ID_SCE:
+                       return 0; /* not implemented */
+               case ID_LI:
+                       return 0; /* can't be linked */
+               case ID_OB:
+                       if(!test) make_local_object((Object*)id);
+                       return 1;
+               case ID_ME:
+                       if(!test) {
+                               make_local_mesh((Mesh*)id);
+                               make_local_key(((Mesh*)id)->key);
+                       }
+                       return 1;
+               case ID_CU:
+                       if(!test) {
+                               make_local_curve((Curve*)id);
+                               make_local_key(((Curve*)id)->key);
+                       }
+                       return 1;
+               case ID_MB:
+                       if(!test) make_local_mball((MetaBall*)id);
+                       return 1;
+               case ID_MA:
+                       if(!test) make_local_material((Material*)id);
+                       return 1;
+               case ID_TE:
+                       if(!test) make_local_texture((Tex*)id);
+                       return 1;
+               case ID_IM:
+                       return 0; /* not implemented */
+               case ID_WV:
+                       return 0; /* deprecated */
+               case ID_LT:
+                       if(!test) make_local_lattice((Lattice*)id);
+                       return 1;
+               case ID_LA:
+                       if(!test) make_local_lamp((Lamp*)id);
+                       return 1;
+               case ID_CA:
+                       if(!test) make_local_camera((Camera*)id);
+                       return 1;
+               case ID_IP:
+                       return 0; /* deprecated */
+               case ID_KE:
+                       if(!test) make_local_key((Key*)id);
+                       return 1;
+               case ID_WO:
+                       if(!test) make_local_world((World*)id);
+                       return 1;
+               case ID_SCR:
+                       return 0; /* can't be linked */
+               case ID_VF:
+                       return 0; /* not implemented */
+               case ID_TXT:
+                       return 0; /* not implemented */
+               case ID_SCRIPT:
+                       return 0; /* deprecated */
+               case ID_SO:
+                       return 0; /* not implemented */
+               case ID_GR:
+                       return 0; /* not implemented */
+               case ID_AR:
+                       if(!test) make_local_armature((bArmature*)id);
+                       return 1;
+               case ID_AC:
+                       if(!test) make_local_action((bAction*)id);
+                       return 1;
+               case ID_NT:
+                       return 0; /* not implemented */
+               case ID_BR:
+                       if(!test) make_local_brush((Brush*)id);
+                       return 1;
+               case ID_PA:
+                       if(!test) make_local_particlesettings((ParticleSettings*)id);
+                       return 1;
+               case ID_WM:
+                       return 0; /* can't be linked */
+               case ID_GD:
+                       return 0; /* not implemented */
+       }
+
+       return 0;
+}
+
+int id_copy(ID *id, ID **newid, int test)
+{
+       if(!test) *newid= NULL;
+
+       /* conventions:
+        * - make shallow copy, only this ID block
+        * - id.us of the new ID is set to 1 */
+       switch(GS(id->name)) {
+               case ID_SCE:
+                       return 0; /* can't be copied from here */
+               case ID_LI:
+                       return 0; /* can't be copied from here */
+               case ID_OB:
+                       if(!test) *newid= (ID*)copy_object((Object*)id);
+                       return 1;
+               case ID_ME:
+                       if(!test) *newid= (ID*)copy_mesh((Mesh*)id);
+                       return 1;
+               case ID_CU:
+                       if(!test) *newid= (ID*)copy_curve((Curve*)id);
+                       return 1;
+               case ID_MB:
+                       if(!test) *newid= (ID*)copy_mball((MetaBall*)id);
+                       return 1;
+               case ID_MA:
+                       if(!test) *newid= (ID*)copy_material((Material*)id);
+                       return 1;
+               case ID_TE:
+                       if(!test) *newid= (ID*)copy_texture((Tex*)id);
+                       return 1;
+               case ID_IM:
+                       return 0; /* not implemented */
+               case ID_WV:
+                       return 0; /* deprecated */
+               case ID_LT:
+                       if(!test) *newid= (ID*)copy_lattice((Lattice*)id);
+                       return 1;
+               case ID_LA:
+                       if(!test) *newid= (ID*)copy_lamp((Lamp*)id);
+                       return 1;
+               case ID_CA:
+                       if(!test) *newid= (ID*)copy_camera((Camera*)id);
+                       return 1;
+               case ID_IP:
+                       return 0; /* deprecated */
+               case ID_KE:
+                       if(!test) *newid= (ID*)copy_key((Key*)id);
+                       return 1;
+               case ID_WO:
+                       if(!test) *newid= (ID*)copy_world((World*)id);
+                       return 1;
+               case ID_SCR:
+                       return 0; /* can't be copied from here */
+               case ID_VF:
+                       return 0; /* not implemented */
+               case ID_TXT:
+                       if(!test) *newid= (ID*)copy_text((Text*)id);
+                       return 1;
+               case ID_SCRIPT:
+                       return 0; /* deprecated */
+               case ID_SO:
+                       return 0; /* not implemented */
+               case ID_GR:
+                       if(!test) *newid= (ID*)copy_group((Group*)id);
+                       return 1;
+               case ID_AR:
+                       if(!test) *newid= (ID*)copy_armature((bArmature*)id);
+                       return 1;
+               case ID_AC:
+                       if(!test) *newid= (ID*)copy_action((bAction*)id);
+                       return 1;
+               case ID_NT:
+                       if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id, 0);
+                       return 1;
+               case ID_BR:
+                       if(!test) *newid= (ID*)copy_brush((Brush*)id);
+                       return 1;
+               case ID_PA:
+                       if(!test) *newid= (ID*)psys_copy_settings((ParticleSettings*)id);
+                       return 1;
+               case ID_WM:
+                       return 0; /* can't be copied from here */
+               case ID_GD:
+                       return 0; /* not implemented */
+       }
+       
+       return 0;
+}
+
+int id_unlink(ID *id, int test)
+{
+       Main *mainlib= G.main;
+       ListBase *lb;
+
+       switch(GS(id->name)) {
+               case ID_TXT:
+                       if(test) return 1;
+                       unlink_text(mainlib, (Text*)id);
+                       break;
+               case ID_GR:
+                       if(test) return 1;
+                       unlink_group((Group*)id);
+                       break;
+               case ID_OB:
+                       if(test) return 1;
+                       unlink_object(NULL, (Object*)id);
+                       break;
+       }
+
+       if(id->us == 0) {
+               if(test) return 1;
+
+               lb= wich_libbase(mainlib, GS(id->name));
+               free_libblock(lb, id);
+
+               return 1;
+       }
+
+       return 0;
+}
+
 ListBase *wich_libbase(Main *mainlib, short type)
 {
        switch( type ) {
@@ -409,13 +627,6 @@ void *alloc_libblock(ListBase *lb, short type, const char *name)
        return id;
 }
 
-/* GS reads the memory pointed at in a specific ordering. 
-   only use this definition, makes little and big endian systems
-   work fine, in conjunction with MAKE_ID */
-
-/* from blendef: */
-#define GS(a)  (*((short *)(a)))
-
 /* by spec, animdata is first item after ID */
 /* we still read ->adt itself, to ensure compiler warns when it doesnt exist */
 static void id_copy_animdata(ID *id)
index e4d73208c6437b177f34d4b1e9a27d3ffd04c78a..de2118af2020dfbcc324898162e063a35e0785c6 100644 (file)
 #include "BKE_blender.h"
 #include "BKE_sca.h"
 
-//#include "wm_event_types.h"
-
-void free_text_controllers(Text *txt)
-{
-       Object *ob;
-       bController *cont;
-       
-       ob= G.main->object.first;
-       while(ob) {
-               cont= ob->controllers.first;
-               while(cont) {
-                       if(cont->type==CONT_PYTHON) {
-                               bPythonCont *pc;
-                               
-                               pc= cont->data;
-                               if(pc->text==txt) pc->text= NULL;
-                       }
-                       cont= cont->next;
-               }
-               ob= ob->id.next;
-       }
-}
-
-
 /* ******************* SENSORS ************************ */
 
 void free_sensor(bSensor *sens)
index 10f6a8cf47c1a9c4cac567fb4a3891c875f6f56e..6f9ed3e09784f8978538cf7b51651795714251c2 100644 (file)
@@ -860,14 +860,3 @@ float get_render_aosss_error(RenderData *r, float error)
                return error;
 }
 
-void free_dome_warp_text(struct Text *txt)
-{
-       Scene *scene;
-
-       scene = G.main->scene.first;
-       while(scene) {
-               if (scene->r.dometext == txt)
-                       scene->r.dometext = NULL;
-               scene = scene->id.next;
-       }
-}
index 8e3d59bbc5869985a5ac92170d3fd27562640bfc..dac426de4eb6e152b62a6cee0ad5886a94d2df3b 100644 (file)
 
 #include "BLI_blenlib.h"
 
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_controller_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 #include "DNA_text_types.h"
 
-#include "BKE_utildefines.h"
-#include "BKE_text.h"
-#include "BKE_library.h"
+#include "BKE_depsgraph.h"
 #include "BKE_global.h"
+#include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_text.h"
+#include "BKE_utildefines.h"
 
 #ifndef DISABLE_PYTHON
 #include "BPY_extern.h"
@@ -451,6 +459,85 @@ Text *copy_text(Text *ta)
        return tan;
 }
 
+void unlink_text(Main *bmain, Text *text)
+{
+       bScreen *scr;
+       ScrArea *area;
+       SpaceLink *sl;
+       Scene *scene;
+       Object *ob;
+       bController *cont;
+       bConstraint *con;
+       short update;
+
+       /* dome */
+       for(scene=bmain->scene.first; scene; scene=scene->id.next)
+               if(scene->r.dometext == text)
+                       scene->r.dometext = NULL;
+       
+       for(ob=bmain->object.first; ob; ob=ob->id.next) {
+               /* game controllers */
+               for(cont=ob->controllers.first; cont; cont=cont->next) {
+                       if(cont->type==CONT_PYTHON) {
+                               bPythonCont *pc;
+                               
+                               pc= cont->data;
+                               if(pc->text==text) pc->text= NULL;
+                       }
+               }
+
+               /* pyconstraints */
+               update = 0;
+
+               if(ob->type==OB_ARMATURE && ob->pose) {
+                       bPoseChannel *pchan;
+                       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                               for(con = pchan->constraints.first; con; con=con->next) {
+                                       if(con->type==CONSTRAINT_TYPE_PYTHON) {
+                                               bPythonConstraint *data = con->data;
+                                               if (data->text==text) data->text = NULL;
+                                               update = 1;
+                                               
+                                       }
+                               }
+                       }
+               }
+
+               for(con = ob->constraints.first; con; con=con->next) {
+                       if(con->type==CONSTRAINT_TYPE_PYTHON) {
+                               bPythonConstraint *data = con->data;
+                               if (data->text==text) data->text = NULL;
+                               update = 1;
+                       }
+               }
+               
+               if(update)
+                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       }
+
+       /* pynodes */
+       // XXX nodeDynamicUnlinkText(&text->id);
+       
+       /* text space */
+       for(scr= bmain->screen.first; scr; scr= scr->id.next) {
+               for(area= scr->areabase.first; area; area= area->next) {
+                       for(sl= area->spacedata.first; sl; sl= sl->next) {
+                               if(sl->spacetype==SPACE_TEXT) {
+                                       SpaceText *st= (SpaceText*) sl;
+                                       
+                                       if(st->text==text) {
+                                               st->text= NULL;
+                                               st->top= 0;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       text->id.us= 0;
+}
+
+
 /*****************************/
 /* Editing utility functions */
 /*****************************/
index 0d7cd26324579dadb21fe0cc94ff6a21bc414bf2..1036b4ccd8f7b31a71becab725a6e18d9232f506 100644 (file)
@@ -238,7 +238,7 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
        col= uiLayoutColumn(layout, 0);
                /* current Grease Pencil block */
                // TODO: show some info about who owns this?
-               uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", "GPENCIL_OT_data_unlink"); 
+               uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink"); 
                
                /* add new layer button - can be used even when no data, since it can add a new block too */
                uiItemO(col, NULL, 0, "GPENCIL_OT_layer_add");
index 0cb6964b39eb13da80f6fd14822651e2920be291..e2338078a8ae4bfb9ca5c4eef4372fe70d308061 100644 (file)
@@ -633,7 +633,7 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout);
 /* templates */
 void uiTemplateHeader(uiLayout *layout, struct bContext *C, int menus);
 void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
-       char *newop, char *unlinkop);
+       char *newop, char *openop, char *unlinkop);
 uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr);
 uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
 void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot);
index d253948e2e8eca608e41afbdd7a5daf37b03f672..2b7d6f383bfa8714b6e8848ca1bf9d477523f910 100644 (file)
@@ -157,7 +157,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 {
        TemplateID *template= (TemplateID*)arg_litem;
        PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
-       ID *id= idptr.data;
+       ID *id= idptr.data, *newid;
        int event= GET_INT_FROM_POINTER(arg_event);
        
        switch(event) {
@@ -185,28 +185,48 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
                        }
                        else return;
                        break;
-#if 0
-               case UI_ID_ALONE:
-                       if(!id || id->us < 1)
-                               return;
-                       break;
                case UI_ID_LOCAL:
-                       if(!id || id->us < 1)
-                               return;
+                       if(id) {
+                               if(id_make_local(id, 0)) {
+                                       /* reassign to get get proper updates/notifiers */
+                                       idptr= RNA_property_pointer_get(&template->ptr, template->prop);
+                                       RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+                                       RNA_property_update(C, &template->ptr, template->prop);
+                               }
+                       }
                        break;
+               case UI_ID_ALONE:
+                       if(id) {
+                               /* make copy */
+                               if(id_copy(id, &newid, 0) && newid) {
+                                       /* 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);
+                               }
+                       }
+                       break;
+#if 0
                case UI_ID_AUTO_NAME:
                        break;
 #endif
        }
 }
 
-static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *unlinkop)
+static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop)
 {
        uiBut *but;
        PointerRNA idptr;
        ListBase *lb;
+       ID *id, *idfrom;
 
        idptr= RNA_property_pointer_get(&template->ptr, template->prop);
+       id= idptr.data;
+       idfrom= template->ptr.id.data;
        lb= template->idlb;
 
        uiBlockBeginAlign(block);
@@ -221,33 +241,86 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
                        but->flag|= UI_HAS_ICON;
                        but->flag|= UI_ICON_LEFT;
                }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
        }
 
        /* text button with name */
-       if(idptr.data) {
+       if(id) {
                char name[64];
 
-               //text_idbutton(idptr.data, name);
+               //text_idbutton(id, name);
                name[0]= '\0';
                but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
                uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
+
+               if(id->lib) {
+                       if(id->flag & LIB_INDIRECT) {
+                               but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
+                                       "Indirect library datablock, cannot change.");
+                               uiButSetFlag(but, UI_BUT_DISABLED);
+                       }
+                       else {
+                               but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
+                                       "Direct linked library datablock, click to make local.");
+                               if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
+                                       uiButSetFlag(but, UI_BUT_DISABLED);
+                       }
+
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
+               }
+
+               if(id->us > 1) {
+                       char str[32];
+
+                       sprintf(str, "%d", id->us);
+
+                       if(id->us<10)
+                               but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
+                       else
+                               but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
+
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
+                       if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib))
+                               uiButSetFlag(but, UI_BUT_DISABLED);
+               }
        }
        
        if(flag & UI_ID_ADD_NEW) {
-               int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
+               int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
                
                if(newop) {
-                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, (idptr.data)? "": "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
                else {
-                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (idptr.data)? "": "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
+       }
+
+       if(flag & UI_ID_OPEN) {
+               int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
+               
+               if(openop) {
+                       but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_REGION_WIN, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+               }
+               else {
+                       but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+                       uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
+               }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
        }
        
        /* delete button */
-       if(idptr.data && (flag & UI_ID_DELETE)) {
+       if(id && (flag & UI_ID_DELETE)) {
                if(unlinkop) {
                        but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
                }
@@ -255,12 +328,15 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
                        but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
                }
+
+               if((idfrom && idfrom->lib))
+                       uiButSetFlag(but, UI_BUT_DISABLED);
        }
        
        uiBlockEndAlign(block);
 }
 
-void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *unlinkop)
+void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
 {
        TemplateID *template;
        uiBlock *block;
@@ -286,6 +362,8 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
 
        if(newop)
                flag |= UI_ID_ADD_NEW;
+       if(openop)
+               flag |= UI_ID_OPEN;
 
        type= RNA_property_pointer_type(ptr, prop);
        template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
@@ -293,7 +371,7 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
        if(template->idlb) {
                uiLayoutRow(layout, 1);
                block= uiLayoutGetBlock(layout);
-               template_ID(C, block, template, type, flag, newop, unlinkop);
+               template_ID(C, block, template, type, flag, newop, openop, unlinkop);
        }
 
        MEM_freeN(template);
index 53882ad8424ebc4d4ae33fdfa8f9375689790160..0ae987f23080d7aa07be320f7b155d175920e570 100644 (file)
@@ -2951,10 +2951,10 @@ static int make_proxy_invoke (bContext *C, wmOperator *op, wmEvent *evt)
        else if (ob->id.lib) {
                uiPopupMenu *pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
                uiLayout *layout= uiPupMenuLayout(pup);
-               PointerRNA props_ptr = {0};
+               PointerRNA props_ptr;
                
                /* create operator menu item with relevant properties filled in */
-               props_ptr= uiItemFullO(layout, op->type->name, 0, op->idname, props_ptr.data, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
+               props_ptr= uiItemFullO(layout, op->type->name, 0, op->idname, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
                RNA_string_set(&props_ptr, "object", ob->id.name+2);
                
                /* present the menu and be done... */
index d17391811bbb2248786059b8243a18cc8fdcb79d..714ebcef0fb5713a64f0967e4fc582af7f35cad9 100644 (file)
@@ -349,8 +349,14 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                        
                        for(base= sce->base.first; base; base= base->next) {
                                if(base->object->id.name[2]=='p') {
-                                       if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL))
-                                               assign_material(base->object, mat, base->object->actcol);
+                                       if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL)) {
+                                               /* don't use assign_material, it changed mat->id.us, which shows in the UI */
+                                               Material ***matar= give_matarar(base->object);
+                                               int actcol= MAX2(base->object->actcol > 0, 1) - 1;
+
+                                               if(matar && actcol < base->object->totcol)
+                                                       (*matar)[actcol]= mat;
+                                       }
                                }
                        }
                }
index bbf1358a37ccf10f5bb97ef33e6898870f0a3e31..8532d78aa064150727a216472452fc3c9ad29897 100644 (file)
@@ -211,7 +211,7 @@ static void nla_panel_animdata (const bContext *C, Panel *pa)
        /* Active Action Properties ------------------------------------- */
        /* action */
        row= uiLayoutRow(layout, 1);
-               uiTemplateID(row, (bContext *)C, &adt_ptr, "action", NULL, NULL/*"ACT_OT_new", "ACT_OT_unlink"*/); // XXX: need to make these operators
+               uiTemplateID(row, (bContext *)C, &adt_ptr, "action", NULL /*"ACT_OT_new"*/, NULL, NULL /*"ACT_OT_unlink"*/); // XXX: need to make these operators
        
        /* extrapolation */
        row= uiLayoutRow(layout, 1);
index cb425274fc07e1e844df82b1e7f2a13f62416403..4847f2f074125cbe1ae6523d5fff32bf048a5145 100644 (file)
@@ -83,8 +83,6 @@ typedef struct FlattenString {
 int flatten_string(struct SpaceText *st, FlattenString *fs, char *in);
 void flatten_string_free(FlattenString *fs);
 
-void unlink_text(struct Text *text);
-
 int wrap_width(struct SpaceText *st, struct ARegion *ar);
 void wrap_offset(struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
 
index a8ef72e327341378c649d1206228c548fbf94cef..7751355a14d35cf4418d6a5c4c3c4fc03026c790 100644 (file)
@@ -273,48 +273,9 @@ void TEXT_OT_reload(wmOperatorType *ot)
 
 /******************* delete operator *********************/
 
-static void text_unlink(Main *bmain, Text *text)
-{
-       bScreen *scr;
-       ScrArea *area;
-       SpaceLink *sl;
-
-       /* XXX this ifdef is in fact dangerous, if python is
-        * disabled it will leave invalid pointers in files! */
-
-#ifndef DISABLE_PYTHON
-       // XXX BPY_free_pyconstraint_links(text);
-       // XXX free_text_controllers(text);
-       // XXX free_dome_warp_text(text);
-
-       /* equivalently for pynodes: */
-       if(0) // XXX nodeDynamicUnlinkText ((ID*)text))
-               ; // XXX notifier: allqueue(REDRAWNODE, 0);
-#endif
-       
-       for(scr= bmain->screen.first; scr; scr= scr->id.next) {
-               for(area= scr->areabase.first; area; area= area->next) {
-                       for(sl= area->spacedata.first; sl; sl= sl->next) {
-                               if(sl->spacetype==SPACE_TEXT) {
-                                       SpaceText *st= (SpaceText*) sl;
-                                       
-                                       if(st->text==text) {
-                                               st->text= NULL;
-                                               st->top= 0;
-                                               
-                                               if(st==area->spacedata.first)
-                                                       ED_area_tag_redraw(area);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       free_libblock(&bmain->text, text);
-}
-
 static int unlink_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain= CTX_data_main(C);
        SpaceText *st= CTX_wm_space_text(C);
        Text *text= CTX_data_edit_text(C);
 
@@ -330,7 +291,8 @@ static int unlink_exec(bContext *C, wmOperator *op)
                }
        }
 
-       text_unlink(CTX_data_main(C), text);
+       unlink_text(bmain, text);
+       free_libblock(&bmain->text, text);
        WM_event_add_notifier(C, NC_TEXT|NA_REMOVED, text);
 
        return OPERATOR_FINISHED;
index 7fc2d75a708b83a6054e3afc7335976c2a3e0ecc..20948843f8a67aa2ae79fc0b1109e0267bfcf324 100644 (file)
@@ -247,6 +247,7 @@ void RNA_api_ui_layout(StructRNA *srna)
        RNA_def_function_flag(func, FUNC_USE_CONTEXT);
        api_ui_item_rna_common(func);
        RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
+       RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block.");
        RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
 
        func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier");