tornavis/source/blender/editors/physics/particle_boids.cc

357 lines
9.1 KiB
C++

/* SPDX-FileCopyrightText: 2009 Janne Karhu. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edphys
*/
#include <cstdlib>
#include "MEM_guardedalloc.h"
#include "DNA_particle_types.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BKE_boids.h"
#include "BKE_context.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "RNA_prototypes.h"
#include "WM_api.hh"
#include "WM_types.hh"
#include "physics_intern.hh"
/************************ add/del boid rule operators *********************/
static int rule_add_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
int type = RNA_enum_get(op->ptr, "type");
BoidRule *rule;
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
state = boid_get_current_state(part->boids);
LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
rule->flag &= ~BOIDRULE_CURRENT;
}
rule = boid_new_rule(type);
rule->flag |= BOIDRULE_CURRENT;
BLI_addtail(&state->rules, rule);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
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", rna_enum_boidrule_type_items, 0, "Type", "");
}
static int rule_del_exec(bContext *C, wmOperator * /*op*/)
{
Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidRule *rule;
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
state = boid_get_current_state(part->boids);
LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
if (rule->flag & BOIDRULE_CURRENT) {
BLI_remlink(&state->rules, rule);
MEM_freeN(rule);
break;
}
}
rule = static_cast<BoidRule *>(state->rules.first);
if (rule) {
rule->flag |= BOIDRULE_CURRENT;
}
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
return OPERATOR_FINISHED;
}
void BOID_OT_rule_del(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Boid Rule";
ot->idname = "BOID_OT_rule_del";
ot->description = "Delete current boid rule";
/* 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 * /*op*/)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
state = boid_get_current_state(part->boids);
LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
BLI_remlink(&state->rules, rule);
BLI_insertlinkbefore(&state->rules, rule->prev, rule);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
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 * /*op*/)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
state = boid_get_current_state(part->boids);
LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
if (rule->flag & BOIDRULE_CURRENT && rule->next) {
BLI_remlink(&state->rules, rule);
BLI_insertlinkafter(&state->rules, rule->next, rule);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
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 * /*op*/)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
state->flag &= ~BOIDSTATE_CURRENT;
}
state = boid_new_state(part->boids);
state->flag |= BOIDSTATE_CURRENT;
BLI_addtail(&part->boids->states, state);
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 * /*op*/)
{
Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidState *state;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
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 = static_cast<BoidState *>(part->boids->states.first);
}
state->flag |= BOIDSTATE_CURRENT;
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
return OPERATOR_FINISHED;
}
void BOID_OT_state_del(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Boid State";
ot->idname = "BOID_OT_state_del";
ot->description = "Delete current boid state";
/* 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 * /*op*/)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidSettings *boids;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
boids = part->boids;
LISTBASE_FOREACH (BoidState *, state, &boids->states) {
if (state->flag & BOIDSTATE_CURRENT && state->prev) {
BLI_remlink(&boids->states, state);
BLI_insertlinkbefore(&boids->states, state->prev, state);
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 * /*op*/)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = static_cast<ParticleSettings *>(ptr.data);
BoidSettings *boids;
if (!part || part->phystype != PART_PHYS_BOIDS) {
return OPERATOR_CANCELLED;
}
boids = part->boids;
LISTBASE_FOREACH (BoidState *, state, &boids->states) {
if (state->flag & BOIDSTATE_CURRENT && state->next) {
BLI_remlink(&boids->states, state);
BLI_insertlinkafter(&boids->states, state->next, state);
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_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;
}