Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / physics / particle_boids.c
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) 2009 Janne Karhu.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edphys
22  */
23
24 #include <stdlib.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_particle_types.h"
29
30 #include "BLI_listbase.h"
31 #include "BLI_utildefines.h"
32
33 #include "BKE_boids.h"
34 #include "BKE_context.h"
35 #include "BKE_main.h"
36 #include "BKE_particle.h"
37
38 #include "DEG_depsgraph.h"
39 #include "DEG_depsgraph_build.h"
40
41 #include "RNA_access.h"
42 #include "RNA_enum_types.h"
43 #include "RNA_define.h"
44
45 #include "WM_api.h"
46 #include "WM_types.h"
47
48 #include "physics_intern.h"
49
50 /************************ add/del boid rule operators *********************/
51 static int rule_add_exec(bContext *C, wmOperator *op)
52 {
53   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
54   ParticleSettings *part = ptr.data;
55   int type = RNA_enum_get(op->ptr, "type");
56
57   BoidRule *rule;
58   BoidState *state;
59
60   if (!part || part->phystype != PART_PHYS_BOIDS) {
61     return OPERATOR_CANCELLED;
62   }
63
64   state = boid_get_current_state(part->boids);
65
66   for (rule = state->rules.first; rule; rule = rule->next) {
67     rule->flag &= ~BOIDRULE_CURRENT;
68   }
69
70   rule = boid_new_rule(type);
71   rule->flag |= BOIDRULE_CURRENT;
72
73   BLI_addtail(&state->rules, rule);
74
75   DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
76
77   return OPERATOR_FINISHED;
78 }
79
80 void BOID_OT_rule_add(wmOperatorType *ot)
81 {
82   /* identifiers */
83   ot->name = "Add Boid Rule";
84   ot->description = "Add a boid rule to the current boid state";
85   ot->idname = "BOID_OT_rule_add";
86
87   /* api callbacks */
88   ot->invoke = WM_menu_invoke;
89   ot->exec = rule_add_exec;
90
91   /* flags */
92   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
93
94   ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_boidrule_type_items, 0, "Type", "");
95 }
96 static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
97 {
98   Main *bmain = CTX_data_main(C);
99   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
100   ParticleSettings *part = ptr.data;
101   BoidRule *rule;
102   BoidState *state;
103
104   if (!part || part->phystype != PART_PHYS_BOIDS) {
105     return OPERATOR_CANCELLED;
106   }
107
108   state = boid_get_current_state(part->boids);
109
110   for (rule = state->rules.first; rule; rule = rule->next) {
111     if (rule->flag & BOIDRULE_CURRENT) {
112       BLI_remlink(&state->rules, rule);
113       MEM_freeN(rule);
114       break;
115     }
116   }
117   rule = state->rules.first;
118
119   if (rule) {
120     rule->flag |= BOIDRULE_CURRENT;
121   }
122
123   DEG_relations_tag_update(bmain);
124   DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
125
126   return OPERATOR_FINISHED;
127 }
128
129 void BOID_OT_rule_del(wmOperatorType *ot)
130 {
131   /* identifiers */
132   ot->name = "Remove Boid Rule";
133   ot->idname = "BOID_OT_rule_del";
134   ot->description = "Delete current boid rule";
135
136   /* api callbacks */
137   ot->exec = rule_del_exec;
138
139   /* flags */
140   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
141 }
142
143 /************************ move up/down boid rule operators *********************/
144 static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
145 {
146   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
147   ParticleSettings *part = ptr.data;
148   BoidRule *rule;
149   BoidState *state;
150
151   if (!part || part->phystype != PART_PHYS_BOIDS) {
152     return OPERATOR_CANCELLED;
153   }
154
155   state = boid_get_current_state(part->boids);
156   for (rule = state->rules.first; rule; rule = rule->next) {
157     if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
158       BLI_remlink(&state->rules, rule);
159       BLI_insertlinkbefore(&state->rules, rule->prev, rule);
160
161       DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
162       break;
163     }
164   }
165
166   return OPERATOR_FINISHED;
167 }
168
169 void BOID_OT_rule_move_up(wmOperatorType *ot)
170 {
171   ot->name = "Move Up Boid Rule";
172   ot->description = "Move boid rule up in the list";
173   ot->idname = "BOID_OT_rule_move_up";
174
175   ot->exec = rule_move_up_exec;
176
177   /* flags */
178   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
179 }
180
181 static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
182 {
183   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
184   ParticleSettings *part = ptr.data;
185   BoidRule *rule;
186   BoidState *state;
187
188   if (!part || part->phystype != PART_PHYS_BOIDS) {
189     return OPERATOR_CANCELLED;
190   }
191
192   state = boid_get_current_state(part->boids);
193   for (rule = state->rules.first; rule; rule = rule->next) {
194     if (rule->flag & BOIDRULE_CURRENT && rule->next) {
195       BLI_remlink(&state->rules, rule);
196       BLI_insertlinkafter(&state->rules, rule->next, rule);
197
198       DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
199       break;
200     }
201   }
202
203   return OPERATOR_FINISHED;
204 }
205
206 void BOID_OT_rule_move_down(wmOperatorType *ot)
207 {
208   ot->name = "Move Down Boid Rule";
209   ot->description = "Move boid rule down in the list";
210   ot->idname = "BOID_OT_rule_move_down";
211
212   ot->exec = rule_move_down_exec;
213
214   /* flags */
215   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
216 }
217
218 /************************ add/del boid state operators *********************/
219 static int state_add_exec(bContext *C, wmOperator *UNUSED(op))
220 {
221   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
222   ParticleSettings *part = ptr.data;
223   BoidState *state;
224
225   if (!part || part->phystype != PART_PHYS_BOIDS) {
226     return OPERATOR_CANCELLED;
227   }
228
229   for (state = part->boids->states.first; state; state = state->next) {
230     state->flag &= ~BOIDSTATE_CURRENT;
231   }
232
233   state = boid_new_state(part->boids);
234   state->flag |= BOIDSTATE_CURRENT;
235
236   BLI_addtail(&part->boids->states, state);
237
238   return OPERATOR_FINISHED;
239 }
240
241 void BOID_OT_state_add(wmOperatorType *ot)
242 {
243   /* identifiers */
244   ot->name = "Add Boid State";
245   ot->description = "Add a boid state to the particle system";
246   ot->idname = "BOID_OT_state_add";
247
248   /* api callbacks */
249   ot->exec = state_add_exec;
250
251   /* flags */
252   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
253 }
254 static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
255 {
256   Main *bmain = CTX_data_main(C);
257   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
258   ParticleSettings *part = ptr.data;
259   BoidState *state;
260
261   if (!part || part->phystype != PART_PHYS_BOIDS) {
262     return OPERATOR_CANCELLED;
263   }
264
265   for (state = part->boids->states.first; state; state = state->next) {
266     if (state->flag & BOIDSTATE_CURRENT) {
267       BLI_remlink(&part->boids->states, state);
268       MEM_freeN(state);
269       break;
270     }
271   }
272
273   /* there must be at least one state */
274   if (!part->boids->states.first) {
275     state = boid_new_state(part->boids);
276     BLI_addtail(&part->boids->states, state);
277   }
278   else {
279     state = part->boids->states.first;
280   }
281
282   state->flag |= BOIDSTATE_CURRENT;
283
284   DEG_relations_tag_update(bmain);
285   DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
286
287   return OPERATOR_FINISHED;
288 }
289
290 void BOID_OT_state_del(wmOperatorType *ot)
291 {
292   /* identifiers */
293   ot->name = "Remove Boid State";
294   ot->idname = "BOID_OT_state_del";
295   ot->description = "Delete current boid state";
296
297   /* api callbacks */
298   ot->exec = state_del_exec;
299
300   /* flags */
301   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
302 }
303
304 /************************ move up/down boid state operators *********************/
305 static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
306 {
307   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
308   ParticleSettings *part = ptr.data;
309   BoidSettings *boids;
310   BoidState *state;
311
312   if (!part || part->phystype != PART_PHYS_BOIDS) {
313     return OPERATOR_CANCELLED;
314   }
315
316   boids = part->boids;
317
318   for (state = boids->states.first; state; state = state->next) {
319     if (state->flag & BOIDSTATE_CURRENT && state->prev) {
320       BLI_remlink(&boids->states, state);
321       BLI_insertlinkbefore(&boids->states, state->prev, state);
322       break;
323     }
324   }
325
326   return OPERATOR_FINISHED;
327 }
328
329 void BOID_OT_state_move_up(wmOperatorType *ot)
330 {
331   ot->name = "Move Up Boid State";
332   ot->description = "Move boid state up in the list";
333   ot->idname = "BOID_OT_state_move_up";
334
335   ot->exec = state_move_up_exec;
336
337   /* flags */
338   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
339 }
340
341 static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
342 {
343   PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
344   ParticleSettings *part = ptr.data;
345   BoidSettings *boids;
346   BoidState *state;
347
348   if (!part || part->phystype != PART_PHYS_BOIDS) {
349     return OPERATOR_CANCELLED;
350   }
351
352   boids = part->boids;
353
354   for (state = boids->states.first; state; state = state->next) {
355     if (state->flag & BOIDSTATE_CURRENT && state->next) {
356       BLI_remlink(&boids->states, state);
357       BLI_insertlinkafter(&boids->states, state->next, state);
358       DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
359       break;
360     }
361   }
362
363   return OPERATOR_FINISHED;
364 }
365
366 void BOID_OT_state_move_down(wmOperatorType *ot)
367 {
368   ot->name = "Move Down Boid State";
369   ot->description = "Move boid state down in the list";
370   ot->idname = "BOID_OT_state_move_down";
371
372   ot->exec = state_move_down_exec;
373
374   /* flags */
375   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
376 }