Refactor/enhance BKE_material_make_local() and BKE_image_make_local().
[blender.git] / source / blender / blenkernel / intern / world.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/world.c
29  *  \ingroup bke
30  */
31
32
33 #include <string.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_world_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_texture_types.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_listbase.h"
44
45 #include "BKE_animsys.h"
46 #include "BKE_global.h"
47 #include "BKE_icons.h"
48 #include "BKE_library.h"
49 #include "BKE_library_query.h"
50 #include "BKE_library_remap.h"
51 #include "BKE_main.h"
52 #include "BKE_node.h"
53 #include "BKE_world.h"
54
55 #include "GPU_material.h"
56
57 /** Free (or release) any data used by this world (does not free the world itself). */
58 void BKE_world_free(World *wrld)
59 {
60         int a;
61
62         BKE_animdata_free((ID *)wrld, false);
63
64         for (a = 0; a < MAX_MTEX; a++) {
65                 MEM_SAFE_FREE(wrld->mtex[a]);
66         }
67
68         /* is no lib link block, but world extension */
69         if (wrld->nodetree) {
70                 ntreeFreeTree(wrld->nodetree);
71                 MEM_freeN(wrld->nodetree);
72                 wrld->nodetree = NULL;
73         }
74
75         GPU_material_free(&wrld->gpumaterial);
76         
77         BKE_icon_id_delete((struct ID *)wrld);
78         BKE_previewimg_free(&wrld->preview);
79 }
80
81 void BKE_world_init(World *wrld)
82 {
83         BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(wrld, id));
84
85         wrld->horr = 0.05f;
86         wrld->horg = 0.05f;
87         wrld->horb = 0.05f;
88         wrld->zenr = 0.01f;
89         wrld->zeng = 0.01f;
90         wrld->zenb = 0.01f;
91         wrld->skytype = 0;
92
93         wrld->exp = 0.0f;
94         wrld->exposure = wrld->range = 1.0f;
95
96         wrld->aodist = 10.0f;
97         wrld->aosamp = 5;
98         wrld->aoenergy = 1.0f;
99         wrld->ao_env_energy = 1.0f;
100         wrld->ao_indirect_energy = 1.0f;
101         wrld->ao_indirect_bounces = 1;
102         wrld->aobias = 0.05f;
103         wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY;
104         wrld->ao_approx_error = 0.25f;
105         
106         wrld->preview = NULL;
107         wrld->miststa = 5.0f;
108         wrld->mistdist = 25.0f;
109 }
110
111 World *add_world(Main *bmain, const char *name)
112 {
113         World *wrld;
114
115         wrld = BKE_libblock_alloc(bmain, ID_WO, name);
116
117         BKE_world_init(wrld);
118
119         return wrld;
120 }
121
122 World *BKE_world_copy(Main *bmain, World *wrld)
123 {
124         World *wrldn;
125         int a;
126         
127         wrldn = BKE_libblock_copy(bmain, &wrld->id);
128         
129         for (a = 0; a < MAX_MTEX; a++) {
130                 if (wrld->mtex[a]) {
131                         wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_world_copy");
132                         memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex));
133                         id_us_plus((ID *)wrldn->mtex[a]->tex);
134                 }
135         }
136
137         if (wrld->nodetree) {
138                 wrldn->nodetree = ntreeCopyTree(bmain, wrld->nodetree);
139         }
140         
141         if (wrld->preview)
142                 wrldn->preview = BKE_previewimg_copy(wrld->preview);
143
144         BLI_listbase_clear(&wrldn->gpumaterial);
145
146         if (ID_IS_LINKED_DATABLOCK(wrld)) {
147                 BKE_id_lib_local_paths(bmain, wrld->id.lib, &wrldn->id);
148         }
149
150         return wrldn;
151 }
152
153 World *localize_world(World *wrld)
154 {
155         World *wrldn;
156         int a;
157         
158         wrldn = BKE_libblock_copy_nolib(&wrld->id, false);
159         
160         for (a = 0; a < MAX_MTEX; a++) {
161                 if (wrld->mtex[a]) {
162                         wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), "localize_world");
163                         memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex));
164                         /* free world decrements */
165                         id_us_plus((ID *)wrldn->mtex[a]->tex);
166                 }
167         }
168
169         if (wrld->nodetree)
170                 wrldn->nodetree = ntreeLocalize(wrld->nodetree);
171         
172         wrldn->preview = NULL;
173         
174         BLI_listbase_clear(&wrldn->gpumaterial);
175         
176         return wrldn;
177 }
178
179 static int extern_local_world_callback(
180         void *UNUSED(user_data), struct ID *UNUSED(id_self), struct ID **id_pointer, int cd_flag)
181 {
182         /* We only tag usercounted ID usages as extern... Why? */
183         if ((cd_flag & IDWALK_USER) && *id_pointer) {
184                 id_lib_extern(*id_pointer);
185         }
186         return IDWALK_RET_NOP;
187 }
188
189 static void expand_local_world(World *wrld)
190 {
191         BKE_library_foreach_ID_link(&wrld->id, extern_local_world_callback, NULL, 0);
192 }
193
194 void BKE_world_make_local(Main *bmain, World *wrld)
195 {
196         bool is_local = false, is_lib = false;
197
198         /* - only lib users: do nothing
199          * - only local users: set flag
200          * - mixed: make copy
201          */
202
203         if (!ID_IS_LINKED_DATABLOCK(wrld)) {
204                 return;
205         }
206
207         BKE_library_ID_test_usages(bmain, wrld, &is_local, &is_lib);
208
209         if (is_local) {
210                 if (!is_lib) {
211                         id_clear_lib_data(bmain, &wrld->id);
212                         expand_local_world(wrld);
213                 }
214                 else {
215                         World *wrld_new = BKE_world_copy(bmain, wrld);
216
217                         wrld_new->id.us = 0;
218
219                         /* Remap paths of new ID using old library as base. */
220                         BKE_id_lib_local_paths(bmain, wrld->id.lib, &wrld_new->id);
221
222                         BKE_libblock_remap(bmain, wrld, wrld_new, ID_REMAP_SKIP_INDIRECT_USAGE);
223                 }
224         }
225 }