1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup bke
19  *
20  * Used for copy/paste operator, (using a temporary file).
21  */
22 
23 #include <stdlib.h>
24 
25 #include "MEM_guardedalloc.h"
26 
27 #include "DNA_scene_types.h"
28 #include "DNA_screen_types.h"
29 #include "DNA_userdef_types.h"
30 #include "DNA_view3d_types.h"
31 #include "DNA_windowmanager_types.h"
32 
33 #include "BLI_blenlib.h"
34 #include "BLI_utildefines.h"
35 
36 #include "IMB_imbuf.h"
37 #include "IMB_moviecache.h"
38 
39 #include "BKE_blender_copybuffer.h" /* own include */
40 #include "BKE_blendfile.h"
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_layer.h"
44 #include "BKE_lib_id.h"
45 #include "BKE_main.h"
46 #include "BKE_scene.h"
47 
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_build.h"
50 
51 #include "BLO_readfile.h"
52 #include "BLO_writefile.h"
53 
54 #include "IMB_colormanagement.h"
55 
56 /* -------------------------------------------------------------------- */
57 /** \name Copy/Paste `.blend`, partial saves.
58  * \{ */
59 
BKE_copybuffer_begin(Main * bmain_src)60 void BKE_copybuffer_begin(Main *bmain_src)
61 {
62   BKE_blendfile_write_partial_begin(bmain_src);
63 }
64 
BKE_copybuffer_tag_ID(ID * id)65 void BKE_copybuffer_tag_ID(ID *id)
66 {
67   BKE_blendfile_write_partial_tag_ID(id, true);
68 }
69 
70 /**
71  * \return Success.
72  */
BKE_copybuffer_save(Main * bmain_src,const char * filename,ReportList * reports)73 bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *reports)
74 {
75   const int write_flags = 0;
76   const eBLO_WritePathRemap remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE;
77 
78   bool retval = BKE_blendfile_write_partial(bmain_src, filename, write_flags, remap_mode, reports);
79 
80   BKE_blendfile_write_partial_end(bmain_src);
81 
82   return retval;
83 }
84 
BKE_copybuffer_read(Main * bmain_dst,const char * libname,ReportList * reports,const uint64_t id_types_mask)85 bool BKE_copybuffer_read(Main *bmain_dst,
86                          const char *libname,
87                          ReportList *reports,
88                          const uint64_t id_types_mask)
89 {
90   BlendHandle *bh = BLO_blendhandle_from_file(libname, reports);
91   if (bh == NULL) {
92     /* Error reports will have been made by BLO_blendhandle_from_file(). */
93     return false;
94   }
95   /* Here appending/linking starts. */
96   const int flag = 0;
97   struct LibraryLink_Params liblink_params;
98   BLO_library_link_params_init(&liblink_params, bmain_dst, flag);
99   Main *mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
100   BLO_library_link_copypaste(mainl, bh, id_types_mask);
101   BLO_library_link_end(mainl, &bh, &liblink_params);
102   /* Mark all library linked objects to be updated. */
103   BKE_main_lib_objects_recalc_all(bmain_dst);
104   IMB_colormanagement_check_file_config(bmain_dst);
105   /* Append, rather than linking. */
106   Library *lib = BLI_findstring(&bmain_dst->libraries, libname, offsetof(Library, filepath_abs));
107   BKE_library_make_local(bmain_dst, lib, NULL, true, false);
108   /* Important we unset, otherwise these object wont
109    * link into other scenes from this blend file.
110    */
111   BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false);
112   BLO_blendhandle_close(bh);
113   return true;
114 }
115 
116 /**
117  * \return Number of IDs directly pasted from the buffer
118  * (does not includes indirectly pulled out ones).
119  */
BKE_copybuffer_paste(bContext * C,const char * libname,const short flag,ReportList * reports,const uint64_t id_types_mask)120 int BKE_copybuffer_paste(bContext *C,
121                          const char *libname,
122                          const short flag,
123                          ReportList *reports,
124                          const uint64_t id_types_mask)
125 {
126   Main *bmain = CTX_data_main(C);
127   Scene *scene = CTX_data_scene(C);
128   ViewLayer *view_layer = CTX_data_view_layer(C);
129   View3D *v3d = CTX_wm_view3d(C); /* may be NULL. */
130   Main *mainl = NULL;
131   Library *lib;
132   BlendHandle *bh;
133 
134   bh = BLO_blendhandle_from_file(libname, reports);
135 
136   if (bh == NULL) {
137     /* error reports will have been made by BLO_blendhandle_from_file() */
138     return 0;
139   }
140 
141   BKE_view_layer_base_deselect_all(view_layer);
142 
143   /* tag everything, all untagged data can be made local
144    * its also generally useful to know what is new
145    *
146    * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */
147   BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
148 
149   /* here appending/linking starts */
150   struct LibraryLink_Params liblink_params;
151   BLO_library_link_params_init_with_context(&liblink_params, bmain, flag, scene, view_layer, v3d);
152   mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
153 
154   const int num_pasted = BLO_library_link_copypaste(mainl, bh, id_types_mask);
155 
156   BLO_library_link_end(mainl, &bh, &liblink_params);
157 
158   /* mark all library linked objects to be updated */
159   BKE_main_lib_objects_recalc_all(bmain);
160   IMB_colormanagement_check_file_config(bmain);
161 
162   /* append, rather than linking */
163   lib = BLI_findstring(&bmain->libraries, libname, offsetof(Library, filepath_abs));
164   BKE_library_make_local(bmain, lib, NULL, true, false);
165 
166   /* important we unset, otherwise these object wont
167    * link into other scenes from this blend file */
168   BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
169 
170   /* recreate dependency graph to include new objects */
171   DEG_relations_tag_update(bmain);
172 
173   /* Tag update the scene to flush base collection settings, since the new object is added to a
174    * new (active) collection, not its original collection, thus need recalculation. */
175   DEG_id_tag_update(&scene->id, 0);
176 
177   BLO_blendhandle_close(bh);
178   /* remove library... */
179 
180   return num_pasted;
181 }
182 
183 /** \} */
184