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 * The Original Code is Copyright (C) 2013 Blender Foundation
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup bke
22 */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_collection_types.h"
27 #include "DNA_freestyle_types.h"
28
29 #include "BLI_blenlib.h"
30 #include "BLI_math.h"
31 #include "BLI_string_utils.h"
32
33 #include "BKE_freestyle.h"
34 #include "BKE_lib_id.h"
35 #include "BKE_linestyle.h"
36
37 // function declarations
38 static FreestyleLineSet *alloc_lineset(void);
39 static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag);
40 static FreestyleModuleConfig *alloc_module(void);
41 static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module);
42
BKE_freestyle_config_init(FreestyleConfig * config)43 void BKE_freestyle_config_init(FreestyleConfig *config)
44 {
45 config->mode = FREESTYLE_CONTROL_EDITOR_MODE;
46
47 BLI_listbase_clear(&config->modules);
48 config->flags = 0;
49 config->sphere_radius = 0.1f;
50 config->dkr_epsilon = 0.0f;
51 config->crease_angle = DEG2RADF(134.43f);
52
53 BLI_listbase_clear(&config->linesets);
54 }
55
BKE_freestyle_config_free(FreestyleConfig * config,const bool do_id_user)56 void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
57 {
58 FreestyleLineSet *lineset;
59
60 for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
61 if (lineset->group) {
62 if (do_id_user) {
63 id_us_min(&lineset->group->id);
64 }
65 lineset->group = NULL;
66 }
67 if (lineset->linestyle) {
68 if (do_id_user) {
69 id_us_min(&lineset->linestyle->id);
70 }
71 lineset->linestyle = NULL;
72 }
73 }
74 BLI_freelistN(&config->linesets);
75 BLI_freelistN(&config->modules);
76 }
77
BKE_freestyle_config_copy(FreestyleConfig * new_config,const FreestyleConfig * config,const int flag)78 void BKE_freestyle_config_copy(FreestyleConfig *new_config,
79 const FreestyleConfig *config,
80 const int flag)
81 {
82 FreestyleLineSet *lineset, *new_lineset;
83 FreestyleModuleConfig *module, *new_module;
84
85 new_config->mode = config->mode;
86 new_config->flags = config->flags;
87 new_config->sphere_radius = config->sphere_radius;
88 new_config->dkr_epsilon = config->dkr_epsilon;
89 new_config->crease_angle = config->crease_angle;
90
91 BLI_listbase_clear(&new_config->linesets);
92 for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
93 new_lineset = alloc_lineset();
94 copy_lineset(new_lineset, lineset, flag);
95 BLI_addtail(&new_config->linesets, (void *)new_lineset);
96 }
97
98 BLI_listbase_clear(&new_config->modules);
99 for (module = (FreestyleModuleConfig *)config->modules.first; module; module = module->next) {
100 new_module = alloc_module();
101 copy_module(new_module, module);
102 BLI_addtail(&new_config->modules, (void *)new_module);
103 }
104 }
105
copy_lineset(FreestyleLineSet * new_lineset,FreestyleLineSet * lineset,const int flag)106 static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag)
107 {
108 new_lineset->linestyle = lineset->linestyle;
109 new_lineset->flags = lineset->flags;
110 new_lineset->selection = lineset->selection;
111 new_lineset->qi = lineset->qi;
112 new_lineset->qi_start = lineset->qi_start;
113 new_lineset->qi_end = lineset->qi_end;
114 new_lineset->edge_types = lineset->edge_types;
115 new_lineset->exclude_edge_types = lineset->exclude_edge_types;
116 new_lineset->group = lineset->group;
117 strcpy(new_lineset->name, lineset->name);
118
119 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
120 id_us_plus((ID *)new_lineset->linestyle);
121 id_us_plus((ID *)new_lineset->group);
122 }
123 }
124
alloc_module(void)125 static FreestyleModuleConfig *alloc_module(void)
126 {
127 return (FreestyleModuleConfig *)MEM_callocN(sizeof(FreestyleModuleConfig),
128 "style module configuration");
129 }
130
BKE_freestyle_module_add(FreestyleConfig * config)131 FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config)
132 {
133 FreestyleModuleConfig *module_conf = alloc_module();
134 BLI_addtail(&config->modules, (void *)module_conf);
135 module_conf->script = NULL;
136 module_conf->is_displayed = 1;
137 return module_conf;
138 }
139
copy_module(FreestyleModuleConfig * new_module,FreestyleModuleConfig * module)140 static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module)
141 {
142 new_module->script = module->script;
143 new_module->is_displayed = module->is_displayed;
144 }
145
BKE_freestyle_module_delete(FreestyleConfig * config,FreestyleModuleConfig * module_conf)146 bool BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
147 {
148 if (BLI_findindex(&config->modules, module_conf) == -1) {
149 return false;
150 }
151 BLI_freelinkN(&config->modules, module_conf);
152 return true;
153 }
154
155 /**
156 * Reinsert \a module_conf offset by \a direction from current position.
157 * \return if position of \a module_conf changed.
158 */
BKE_freestyle_module_move(FreestyleConfig * config,FreestyleModuleConfig * module_conf,int direction)159 bool BKE_freestyle_module_move(FreestyleConfig *config,
160 FreestyleModuleConfig *module_conf,
161 int direction)
162 {
163 return ((BLI_findindex(&config->modules, module_conf) > -1) &&
164 (BLI_listbase_link_move(&config->modules, module_conf, direction) == true));
165 }
166
BKE_freestyle_lineset_unique_name(FreestyleConfig * config,FreestyleLineSet * lineset)167 void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset)
168 {
169 BLI_uniquename(&config->linesets,
170 lineset,
171 "FreestyleLineSet",
172 '.',
173 offsetof(FreestyleLineSet, name),
174 sizeof(lineset->name));
175 }
176
alloc_lineset(void)177 static FreestyleLineSet *alloc_lineset(void)
178 {
179 return (FreestyleLineSet *)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set");
180 }
181
BKE_freestyle_lineset_add(struct Main * bmain,FreestyleConfig * config,const char * name)182 FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain,
183 FreestyleConfig *config,
184 const char *name)
185 {
186 int lineset_index = BLI_listbase_count(&config->linesets);
187
188 FreestyleLineSet *lineset = alloc_lineset();
189 BLI_addtail(&config->linesets, (void *)lineset);
190 BKE_freestyle_lineset_set_active_index(config, lineset_index);
191
192 lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
193 lineset->flags |= FREESTYLE_LINESET_ENABLED;
194 lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES |
195 FREESTYLE_SEL_IMAGE_BORDER;
196 lineset->qi = FREESTYLE_QI_VISIBLE;
197 lineset->qi_start = 0;
198 lineset->qi_end = 100;
199 lineset->edge_types = FREESTYLE_FE_SILHOUETTE | FREESTYLE_FE_BORDER | FREESTYLE_FE_CREASE;
200 lineset->exclude_edge_types = 0;
201 lineset->group = NULL;
202 if (name) {
203 BLI_strncpy(lineset->name, name, sizeof(lineset->name));
204 }
205 else if (lineset_index > 0) {
206 sprintf(lineset->name, "LineSet %i", lineset_index + 1);
207 }
208 else {
209 strcpy(lineset->name, "LineSet");
210 }
211 BKE_freestyle_lineset_unique_name(config, lineset);
212
213 return lineset;
214 }
215
BKE_freestyle_lineset_delete(FreestyleConfig * config,FreestyleLineSet * lineset)216 bool BKE_freestyle_lineset_delete(FreestyleConfig *config, FreestyleLineSet *lineset)
217 {
218 if (BLI_findindex(&config->linesets, lineset) == -1) {
219 return false;
220 }
221 if (lineset->group) {
222 id_us_min(&lineset->group->id);
223 }
224 if (lineset->linestyle) {
225 id_us_min(&lineset->linestyle->id);
226 }
227 BLI_remlink(&config->linesets, lineset);
228 MEM_freeN(lineset);
229 BKE_freestyle_lineset_set_active_index(config, 0);
230 return true;
231 }
232
BKE_freestyle_lineset_get_active(FreestyleConfig * config)233 FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config)
234 {
235 FreestyleLineSet *lineset;
236
237 for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
238 if (lineset->flags & FREESTYLE_LINESET_CURRENT) {
239 return lineset;
240 }
241 }
242 return NULL;
243 }
244
BKE_freestyle_lineset_get_active_index(FreestyleConfig * config)245 short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config)
246 {
247 FreestyleLineSet *lineset;
248 short i;
249
250 for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset;
251 lineset = lineset->next, i++) {
252 if (lineset->flags & FREESTYLE_LINESET_CURRENT) {
253 return i;
254 }
255 }
256 return 0;
257 }
258
BKE_freestyle_lineset_set_active_index(FreestyleConfig * config,short index)259 void BKE_freestyle_lineset_set_active_index(FreestyleConfig *config, short index)
260 {
261 FreestyleLineSet *lineset;
262 short i;
263
264 for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset;
265 lineset = lineset->next, i++) {
266 if (i == index) {
267 lineset->flags |= FREESTYLE_LINESET_CURRENT;
268 }
269 else {
270 lineset->flags &= ~FREESTYLE_LINESET_CURRENT;
271 }
272 }
273 }
274