/** * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2009 Janne Karhu. * All rights reserved. * * Contributor(s): Blender Foundation * * ***** END GPL LICENSE BLOCK ***** */ #include #include "MEM_guardedalloc.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "BKE_boids.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_particle.h" #include "BLI_listbase.h" #include "RNA_access.h" #include "RNA_enum_types.h" #include "RNA_define.h" #include "WM_api.h" #include "WM_types.h" #include "physics_intern.h" /************************ add/del boid rule operators *********************/ static int rule_add_exec(bContext *C, wmOperator *op) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob= ptr.id.data; ParticleSettings *part; int type= RNA_enum_get(op->ptr, "type"); BoidRule *rule; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; part = psys->part; state = boid_get_current_state(part->boids); for(rule=state->rules.first; rule; rule=rule->next) rule->flag &= ~BOIDRULE_CURRENT; rule = boid_new_rule(type); rule->flag |= BOIDRULE_CURRENT; BLI_addtail(&state->rules, rule); DAG_id_flush_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } void BOID_OT_rule_add(wmOperatorType *ot) { /* identifiers */ ot->name= "Add Boid Rule"; ot->description = "Add a boid rule to the current boid state"; ot->idname= "BOID_OT_rule_add"; /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= rule_add_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->prop= RNA_def_enum(ot->srna, "type", boidrule_type_items, 0, "Type", ""); } static int rule_del_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; BoidRule *rule; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; state = boid_get_current_state(psys->part->boids); for(rule=state->rules.first; rule; rule=rule->next) { if(rule->flag & BOIDRULE_CURRENT) { BLI_remlink(&state->rules, rule); MEM_freeN(rule); break; } } rule = state->rules.first; if(rule) rule->flag |= BOIDRULE_CURRENT; DAG_scene_sort(bmain, scene); DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } void BOID_OT_rule_del(wmOperatorType *ot) { /* identifiers */ ot->name= "Remove Boid Rule"; ot->idname= "BOID_OT_rule_del"; /* api callbacks */ ot->exec= rule_del_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } /************************ move up/down boid rule operators *********************/ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; BoidRule *rule; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; state = boid_get_current_state(psys->part->boids); for(rule = state->rules.first; rule; rule=rule->next) { if(rule->flag & BOIDRULE_CURRENT && rule->prev) { BLI_remlink(&state->rules, rule); BLI_insertlink(&state->rules, rule->prev->prev, rule); DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); break; } } return OPERATOR_FINISHED; } void BOID_OT_rule_move_up(wmOperatorType *ot) { ot->name= "Move Up Boid Rule"; ot->description= "Move boid rule up in the list"; ot->idname= "BOID_OT_rule_move_up"; ot->exec= rule_move_up_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; BoidRule *rule; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; state = boid_get_current_state(psys->part->boids); for(rule = state->rules.first; rule; rule=rule->next) { if(rule->flag & BOIDRULE_CURRENT && rule->next) { BLI_remlink(&state->rules, rule); BLI_insertlink(&state->rules, rule->next, rule); DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); break; } } return OPERATOR_FINISHED; } void BOID_OT_rule_move_down(wmOperatorType *ot) { ot->name= "Move Down Boid Rule"; ot->description= "Move boid rule down in the list"; ot->idname= "BOID_OT_rule_move_down"; ot->exec= rule_move_down_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } /************************ add/del boid state operators *********************/ static int state_add_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob= ptr.id.data; ParticleSettings *part; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; part = psys->part; for(state=part->boids->states.first; state; state=state->next) state->flag &= ~BOIDSTATE_CURRENT; state = boid_new_state(part->boids); state->flag |= BOIDSTATE_CURRENT; BLI_addtail(&part->boids->states, state); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } void BOID_OT_state_add(wmOperatorType *ot) { /* identifiers */ ot->name= "Add Boid State"; ot->description = "Add a boid state to the particle system"; ot->idname= "BOID_OT_state_add"; /* api callbacks */ ot->exec= state_add_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } static int state_del_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; ParticleSettings *part; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; part = psys->part; for(state=part->boids->states.first; state; state=state->next) { if(state->flag & BOIDSTATE_CURRENT) { BLI_remlink(&part->boids->states, state); MEM_freeN(state); break; } } /* there must be at least one state */ if(!part->boids->states.first) { state = boid_new_state(part->boids); BLI_addtail(&part->boids->states, state); } else state = part->boids->states.first; state->flag |= BOIDSTATE_CURRENT; DAG_scene_sort(bmain, scene); DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } void BOID_OT_state_del(wmOperatorType *ot) { /* identifiers */ ot->name= "Remove Boid State"; ot->idname= "BOID_OT_state_del"; /* api callbacks */ ot->exec= state_del_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } /************************ move up/down boid state operators *********************/ static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; Object *ob = ptr.id.data; BoidSettings *boids; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; boids = psys->part->boids; for(state = boids->states.first; state; state=state->next) { if(state->flag & BOIDSTATE_CURRENT && state->prev) { BLI_remlink(&boids->states, state); BLI_insertlink(&boids->states, state->prev->prev, state); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); break; } } return OPERATOR_FINISHED; } void BOID_OT_state_move_up(wmOperatorType *ot) { ot->name= "Move Up Boid State"; ot->description= "Move boid state up in the list"; ot->idname= "BOID_OT_state_move_up"; ot->exec= state_move_up_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; BoidSettings *boids; BoidState *state; if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS) return OPERATOR_CANCELLED; boids = psys->part->boids; for(state = boids->states.first; state; state=state->next) { if(state->flag & BOIDSTATE_CURRENT && state->next) { BLI_remlink(&boids->states, state); BLI_insertlink(&boids->states, state->next, state); DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } return OPERATOR_FINISHED; } void BOID_OT_state_move_down(wmOperatorType *ot) { ot->name= "Move Down Boid State"; ot->description= "Move boid state down in the list"; ot->idname= "BOID_OT_state_move_down"; ot->exec= state_move_down_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; }