Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / paint_toolslots.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/paint_toolslots.c
22  *  \ingroup bke
23  */
24
25 #include <limits.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_modifier_types.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_brush_types.h"
32
33 #include "BLI_utildefines.h"
34
35 #include "BKE_main.h"
36 #include "BKE_library.h"
37 #include "BKE_brush.h"
38 #include "BKE_paint.h"
39
40 void BKE_paint_toolslots_len_ensure(Paint *paint, int len)
41 {
42         /* Tool slots are 'uchar'. */
43         BLI_assert(len <= UCHAR_MAX);
44         if (paint->tool_slots_len < len) {
45                 paint->tool_slots = MEM_recallocN(paint->tool_slots, sizeof(*paint->tool_slots) * len);
46                 paint->tool_slots_len = len;
47         }
48 }
49
50 static void paint_toolslots_init(Main *bmain, Paint *paint)
51 {
52         if (paint == NULL) {
53                 return;
54         }
55         const eObjectMode ob_mode = paint->runtime.ob_mode;
56         BLI_assert(paint->runtime.tool_offset && ob_mode);
57         for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
58                 if (brush->ob_mode & ob_mode) {
59                         const int slot_index = BKE_brush_tool_get(brush, paint);
60                         BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
61                         if (paint->tool_slots[slot_index].brush == NULL) {
62                                 paint->tool_slots[slot_index].brush = brush;
63                                 id_us_plus(&brush->id);
64                         }
65                 }
66         }
67 }
68
69 void BKE_paint_toolslots_init_from_main(struct Main *bmain)
70 {
71         for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
72                 ToolSettings *ts = scene->toolsettings;
73                 paint_toolslots_init(bmain, &ts->imapaint.paint);
74                 paint_toolslots_init(bmain, &ts->sculpt->paint);
75                 paint_toolslots_init(bmain, &ts->vpaint->paint);
76                 paint_toolslots_init(bmain, &ts->wpaint->paint);
77                 paint_toolslots_init(bmain, &ts->gp_paint->paint);
78         }
79 }
80
81
82 void BKE_paint_toolslots_brush_update_ex(Paint *paint, Brush *brush)
83 {
84         const uint tool_offset = paint->runtime.tool_offset;
85         UNUSED_VARS_NDEBUG(tool_offset);
86         BLI_assert(tool_offset != 0);
87         const int slot_index = BKE_brush_tool_get(brush, paint);
88         BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
89         PaintToolSlot *tslot = &paint->tool_slots[slot_index];
90         id_us_plus(&brush->id);
91         id_us_min(&tslot->brush->id);
92         tslot->brush = brush;
93 }
94
95 void BKE_paint_toolslots_brush_update(Paint *paint)
96 {
97         if (paint->brush == NULL) {
98                 return;
99         }
100         BKE_paint_toolslots_brush_update_ex(paint, paint->brush);
101 }
102
103 /**
104  * Run this to ensure brush types are set for each slot on entering modes
105  * (for new scenes for example).
106  */
107 void BKE_paint_toolslots_brush_validate(Main *bmain, Paint *paint)
108 {
109         /* Clear slots with invalid slots or mode (unlikely but possible). */
110         const uint tool_offset = paint->runtime.tool_offset;
111         UNUSED_VARS_NDEBUG(tool_offset);
112         const eObjectMode ob_mode = paint->runtime.ob_mode;
113         BLI_assert(tool_offset && ob_mode);
114         for (int i = 0; i < paint->tool_slots_len; i++) {
115                 PaintToolSlot *tslot = &paint->tool_slots[i];
116                 if (tslot->brush) {
117                         if ((i != BKE_brush_tool_get(tslot->brush, paint)) ||
118                             (tslot->brush->ob_mode & ob_mode) == 0)
119                         {
120                                 id_us_min(&tslot->brush->id);
121                                 tslot->brush = NULL;
122                         }
123                 }
124         }
125
126         /* Unlikely but possible the active brush is not currently using a slot. */
127         BKE_paint_toolslots_brush_update(paint);
128
129         /* Fill slots from brushes. */
130         paint_toolslots_init(bmain, paint);
131 }
132
133 Brush *BKE_paint_toolslots_brush_get(Paint *paint, int slot_index)
134 {
135         if (slot_index < paint->tool_slots_len) {
136                 PaintToolSlot *tslot = &paint->tool_slots[slot_index];
137                 return tslot->brush;
138         }
139         return NULL;
140 }