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