Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/physics/particle_edit.c')
-rw-r--r--source/blender/editors/physics/particle_edit.c150
1 files changed, 146 insertions, 4 deletions
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index f25679986a5..cf02d2773c0 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -37,6 +37,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_key_types.h"
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -56,6 +57,7 @@
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
+#include "BKE_key.h"
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
@@ -1201,6 +1203,9 @@ void update_world_cos(Object *ob, PTCacheEdit *edit)
mul_m4_v3(hairmat, key->world_co);
}
}
+
+ /* apply hair changes to the active shape key */
+ PE_shapekey_apply(ob, psys);
}
static void update_velocities(PTCacheEdit *edit)
{
@@ -3701,6 +3706,7 @@ typedef struct BrushEdit {
int first;
int lastmouse[2];
float zfac;
+ bool done;
/* optional cached view settings to avoid setting on every mousemove */
PEData data;
@@ -3726,6 +3732,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
bedit->first= 1;
+ bedit->done = false;
op->customdata= bedit;
bedit->scene= scene;
@@ -3881,13 +3888,16 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
}
case PE_BRUSH_ADD:
{
- if (edit->psys && edit->psys->part->from==PART_FROM_FACE) {
+ bool done = (brush->flag & PE_BRUSH_DATA_ADD_SINGLE) && bedit->done;
+ if (!done && edit->psys && edit->psys->part->from==PART_FROM_FACE) {
data.mval= mval;
added= brush_add(&data, brush->count);
if (pset->flag & PE_KEEP_LENGTHS)
recalc_lengths(edit);
+
+ bedit->done = true;
}
else
added= 0;
@@ -4091,10 +4101,11 @@ static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
const float dir[3] = {1.0f, 0.0f, 0.0f};
PointInsideBVH userdata;
-
userdata.bvhdata = data->shape_bvh;
userdata.num_hits = 0;
+ userdata.bvhdata = data->shape_bvh;
+ userdata.num_hits = 0;
BLI_bvhtree_ray_cast_all(shape_bvh->tree, key->co, dir, 0.0f, point_inside_bvh_cb, &userdata);
/* for any point inside a watertight mesh the number of hits is uneven */
@@ -4560,6 +4571,44 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
+bool PE_shapekey_load(Object *ob, ParticleSystem *psys)
+{
+ const int mode_flag = OB_MODE_PARTICLE_EDIT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+
+ if (!is_mode_set)
+ return false;
+
+ if (psys->edit) {
+ /* set the active shape key */
+ KeyBlock *actkb = BKE_keyblock_from_particles(psys);
+
+ if (actkb)
+ BKE_keyblock_convert_to_hair_keys(actkb, ob, psys);
+ }
+
+ return true;
+}
+
+bool PE_shapekey_apply(struct Object *ob, struct ParticleSystem *psys)
+{
+ const int mode_flag = OB_MODE_PARTICLE_EDIT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+
+ if (!is_mode_set)
+ return false;
+
+ if (psys->edit) {
+ /* define the active shape key */
+ KeyBlock *actkb = BKE_keyblock_from_particles(psys);
+
+ if (actkb)
+ BKE_keyblock_convert_from_hair_keys(ob, psys, actkb);
+ }
+
+ return true;
+}
+
/* initialize needed data for bake edit */
void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
@@ -4702,11 +4751,18 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
PTCacheEdit *edit;
ob->mode |= mode_flag;
edit= PE_create_current(scene, ob);
-
+
/* mesh may have changed since last entering editmode.
* note, this may have run before if the edit data was just created, so could avoid this and speed up a little */
- if (edit && edit->psys)
+ if (edit && edit->psys) {
+ /* set the active shape key */
+ KeyBlock *actkb = BKE_keyblock_from_particles(edit->psys);
+
+ if (actkb)
+ BKE_keyblock_convert_to_hair_keys(actkb, ob, edit->psys);
+
recalc_emitter_field(ob, edit->psys);
+ }
toggle_particle_cursor(C, 1);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
@@ -4793,3 +4849,89 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
+/************************ Propagate Shape Key *************************/
+
+static int PE_count_keys(PTCacheEdit *edit)
+{
+ int totkey = 0, p;
+ for (p = 0; p < edit->totpoint; ++p) {
+ totkey += edit->points[p].totkey;
+ }
+ return totkey;
+}
+
+static void shape_propagate(PTCacheEdit *edit, int totkey, KeyBlock *kb, wmOperator *UNUSED(op))
+{
+ PTCacheEditPoint *point;
+ float *fp;
+ int i, k;
+
+ if (kb->totelem != totkey)
+ return;
+
+ fp = kb->data;
+ point = edit->points;
+ for (i = 0; i < edit->totpoint; ++i, ++point) {
+ PTCacheEditKey *key = point->keys;
+ const bool use_point = !(point->flag & PEP_HIDE);
+
+ for (k = 0; k < point->totkey; ++k, ++key) {
+ const bool use_key = (key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE);
+
+ if (use_point && use_key) {
+ copy_v3_v3(fp, key->co);
+
+ point->flag |= PEP_EDIT_RECALC;
+ }
+
+ fp += 3;
+ }
+ }
+}
+
+static int particle_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ Object *ob = ED_object_context(C);
+ ParticleSystem *psys = psys_get_current(ob);
+ PTCacheEdit *edit = psys->edit;
+ Key *key = psys->key;
+ KeyBlock *kb;
+ const int totkey = PE_count_keys(edit);
+
+ if (!key)
+ return OPERATOR_CANCELLED;
+
+ /* we might need world space coordinates, update to be sure */
+ update_world_cos(ob, edit);
+
+ for (kb = key->block.first; kb; kb = kb->next)
+ shape_propagate(edit, totkey, kb, op);
+
+ update_world_cos(ob, edit);
+ PE_update_object(scene, ob, 1);
+
+ if (!(pset->flag & PE_KEEP_LENGTHS))
+ recalc_lengths(edit);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void PARTICLE_OT_shape_propagate_to_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Shape Propagate";
+ ot->description = "Apply selected vertex locations to all other shape keys";
+ ot->idname = "PARTICLE_OT_shape_propagate_to_all";
+
+ /* api callbacks */
+ ot->exec = particle_shape_propagate_to_all_exec;
+ ot->poll = PE_hair_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}