Brush Datablock:
[blender.git] / source / blender / blenkernel / intern / brush.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_brush_types.h"
36 #include "DNA_image_types.h"
37 #include "DNA_scene_types.h"
38
39 #include "BLI_blenlib.h"
40
41 #include "BKE_brush.h"
42 #include "BKE_global.h"
43 #include "BKE_library.h"
44 #include "BKE_main.h"
45
46 Brush *add_brush(char *name)
47 {
48         Brush *brush;
49
50         brush= alloc_libblock(&G.main->brush, ID_BR, name);
51
52         brush->rgb[0]= 1.0f;
53         brush->rgb[1]= 1.0f;
54         brush->rgb[2]= 1.0f;
55         brush->alpha= 0.2f;
56         brush->size= 25;
57         brush->timing= 100.0f;
58         brush->innerradius= 0.5f;
59         brush->clone.alpha= 0.5;
60
61         /* enable fake user by default */
62         brush_toggle_fake_user(brush);
63         
64         return brush;   
65 }
66
67 Brush *copy_brush(Brush *brush)
68 {
69         Brush *brushn;
70         
71         brushn= copy_libblock(brush);
72
73         /* enable fake user by default */
74         if (!(brushn->id.flag & LIB_FAKEUSER))
75                 brush_toggle_fake_user(brushn);
76         
77         return brushn;
78 }
79
80 /* not brush itself */
81 void free_brush(Brush *brush)
82 {
83 }
84
85 void make_local_brush(Brush *brush)
86 {
87         /* don't forget: add stuff texture make local once texture bruses are added*/
88
89         /* - only lib users: do nothing
90             * - only local users: set flag
91             * - mixed: make copy
92             */
93         
94         Brush *brushn;
95         Scene *scene;
96         int local= 0, lib= 0;
97
98         if(brush->id.lib==0) return;
99
100         if(brush->clone.image) {
101         /* special case: ima always local immediately */
102                 brush->clone.image->id.lib= 0;
103                 brush->clone.image->id.flag= LIB_LOCAL;
104                 new_id(0, (ID *)brush->clone.image, 0);
105     }
106
107         for(scene= G.main->scene.first; scene; scene=scene->id.next)
108                 if(scene->toolsettings->imapaint.brush==brush) {
109                         if(scene->id.lib) lib= 1;
110                         else local= 1;
111                 }
112         
113         if(local && lib==0) {
114                 brush->id.lib= 0;
115                 brush->id.flag= LIB_LOCAL;
116                 new_id(0, (ID *)brush, 0);
117
118                 /* enable fake user by default */
119                 if (!(brush->id.flag & LIB_FAKEUSER))
120                         brush_toggle_fake_user(brush);
121         }
122         else if(local && lib) {
123                 brushn= copy_brush(brush);
124                 brushn->id.us= 1; /* only keep fake user */
125                 brushn->id.flag |= LIB_FAKEUSER;
126                 
127                 for(scene= G.main->scene.first; scene; scene=scene->id.next)
128                         if(scene->toolsettings->imapaint.brush==brush)
129                                 if(scene->id.lib==0) {
130                                         scene->toolsettings->imapaint.brush= brushn;
131                                         brushn->id.us++;
132                                         brush->id.us--;
133                                 }
134         }
135 }
136
137 static void brush_blend_mix(char *cp, char *cp1, char *cp2, int fac)
138 {
139         /* this and other blending modes previously used >>8 instead of /255. both
140            are not equivalent (>>8 is /256), and the former results in rounding
141            errors that can turn colors black fast */
142         int mfac= 255-fac;
143         cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
144         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
145         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
146 }
147
148 static void brush_blend_add(char *cp, char *cp1, char *cp2, int fac)
149 {
150         int temp;
151
152         temp= cp1[0] + ((fac*cp2[0])/255);
153         if(temp>254) cp[0]= 255; else cp[0]= temp;
154         temp= cp1[1] + ((fac*cp2[1])/255);
155         if(temp>254) cp[1]= 255; else cp[1]= temp;
156         temp= cp1[2] + ((fac*cp2[2])/255);
157         if(temp>254) cp[2]= 255; else cp[2]= temp;
158 }
159
160 static void brush_blend_sub(char *cp, char *cp1, char *cp2, int fac)
161 {
162         int temp;
163
164         temp= cp1[0] - ((fac*cp2[0])/255);
165         if(temp<0) cp[0]= 0; else cp[0]= temp;
166         temp= cp1[1] - ((fac*cp2[1])/255);
167         if(temp<0) cp[1]= 0; else cp[1]= temp;
168         temp= cp1[2] - ((fac*cp2[2])/255);
169         if(temp<0) cp[2]= 0; else cp[2]= temp;
170 }
171
172 static void brush_blend_mul(char *cp, char *cp1, char *cp2, int fac)
173 {
174         int mfac= 255-fac;
175         
176         /* first mul, then blend the fac */
177         cp[0]= (mfac*cp1[0] + fac*((cp2[0]*cp1[0])/255))/255;
178         cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255))/255;
179         cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255))/255;
180 }
181
182 static void brush_blend_lighten(char *cp, char *cp1, char *cp2, int fac)
183 {
184         /* See if are lighter, if so mix, else dont do anything.
185         if the paint col is darker then the original, then ignore */
186         if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
187                 cp[0]= cp1[0];
188                 cp[1]= cp1[1];
189                 cp[2]= cp1[2];
190         }
191         else
192                 brush_blend_mix(cp, cp1, cp2, fac);
193 }
194
195 static void brush_blend_darken(char *cp, char *cp1, char *cp2, int fac)
196 {
197         /* See if were darker, if so mix, else dont do anything.
198         if the paint col is brighter then the original, then ignore */
199         if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
200                 cp[0]= cp1[0];
201                 cp[1]= cp1[1];
202                 cp[2]= cp1[2];
203         }
204         else
205                 brush_blend_mix(cp, cp1, cp2, fac);
206 }
207
208 void brush_blend_rgb(char *outcol, char *col1, char *col2, int fac, short mode)
209 {
210         if (fac==0) {
211                 outcol[0]= col1[0];
212                 outcol[1]= col1[1];
213                 outcol[2]= col1[2];
214         }
215         else {
216                 switch (mode) {
217                         case BRUSH_BLEND_MIX:
218                                 brush_blend_mix(outcol, col1, col2, fac); break;
219                         case BRUSH_BLEND_ADD:
220                                 brush_blend_add(outcol, col1, col2, fac); break;
221                         case BRUSH_BLEND_SUB:
222                                 brush_blend_sub(outcol, col1, col2, fac); break;
223                         case BRUSH_BLEND_MUL:
224                                 brush_blend_mul(outcol, col1, col2, fac); break;
225                         case BRUSH_BLEND_LIGHTEN:
226                                 brush_blend_lighten(outcol, col1, col2, fac); break;
227                         case BRUSH_BLEND_DARKEN:
228                                 brush_blend_darken(outcol, col1, col2, fac); break;
229                         default:
230                                 brush_blend_mix(outcol, col1, col2, fac); break;
231                 }
232         }
233 }
234
235 int brush_set_nr(Brush **current_brush, int nr)
236 {
237         ID *idtest, *id;
238         
239         id= (ID*)(*current_brush);
240         idtest= (ID*)BLI_findlink(&G.main->brush, nr-1);
241         
242         if(idtest==0) { /* new brush */
243                 if(id) idtest= (ID *)copy_brush((Brush *)id);
244                 else idtest= (ID *)add_brush("Brush");
245                 idtest->us--;
246         }
247         if(idtest!=id) {
248                 brush_delete(current_brush);
249                 *current_brush= (Brush *)idtest;
250                 id_us_plus(idtest);
251
252                 return 1;
253         }
254
255         return 0;
256 }
257
258 int brush_delete(Brush **current_brush)
259 {
260         if (*current_brush) {
261                 (*current_brush)->id.us--;
262                 *current_brush= NULL;
263                 return 1;
264         }
265
266         return 0;
267 }
268
269 void brush_toggle_fake_user(Brush *brush)
270 {
271         ID *id= (ID*)brush;
272         if(id) {
273                 if(id->flag & LIB_FAKEUSER) {
274                         id->flag -= LIB_FAKEUSER;
275                         id->us--;
276                 } else {
277                         id->flag |= LIB_FAKEUSER;
278                         id_us_plus(id);
279                 }
280         }
281 }
282
283 int brush_clone_image_set_nr(Brush *brush, int nr)
284 {
285         if(brush && nr > 0) {
286                 Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1);
287
288                 if(ima) {
289                         brush_clone_image_delete(brush);
290                         brush->clone.image= ima;
291                         id_us_plus(&ima->id);
292                         brush->clone.offset[0]= brush->clone.offset[1]= 0.0f;
293
294                         return 1;
295                 }
296         }
297
298         return 0;
299 }
300
301 int brush_clone_image_delete(Brush *brush)
302 {
303         if (brush && brush->clone.image) {
304                 brush->clone.image->id.us--;
305                 brush->clone.image= NULL;
306                 return 1;
307         }
308
309         return 0;
310 }
311
312 void brush_check_exists(Brush **brush)
313 {
314         if(*brush==NULL)
315                 brush_set_nr(brush, 1);
316 }
317