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/makesrna/intern/rna_particle.c')
-rw-r--r--source/blender/makesrna/intern/rna_particle.c132
1 files changed, 111 insertions, 21 deletions
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 3067a5a9453..13b068c2be5 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -243,35 +243,87 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu
}
}
+/* Helper function which returns index of the given hair_key in particle which owns it.
+ * Works with cases when hair_key is coming from the particle which was passed here, and from the
+ * original particle of the given one.
+ *
+ * Such trickery is needed to allow modification of hair keys in the original object using
+ * evaluated particle and object to access proper hair matrix. */
+static int hair_key_index_get(/*const*/ HairKey *hair_key,
+ /*const*/ ParticleSystemModifierData *modifier,
+ /*const*/ ParticleData *particle)
+{
+ if (ARRAY_HAS_ITEM(hair_key, particle->hair, particle->totkey)) {
+ return hair_key - particle->hair;
+ }
+
+ const ParticleSystem *particle_system = modifier->psys;
+ const int particle_index = particle - particle_system->particles;
+
+ const ParticleSystemModifierData *original_modifier = (ParticleSystemModifierData *)
+ BKE_modifier_get_original(&modifier->modifier);
+ const ParticleSystem *original_particle_system = original_modifier->psys;
+ const ParticleData *original_particle = &original_particle_system->particles[particle_index];
+
+ if (ARRAY_HAS_ITEM(hair_key, original_particle->hair, original_particle->totkey)) {
+ return hair_key - original_particle->hair;
+ }
+
+ return -1;
+}
+
+/* Set hair_key->co to the given coordinate in object space (the given coordinate will be
+ * converted to the proper space).
+ *
+ * The hair_key can be coming from both original and evaluated object. Object, modifier and
+ * particle are to be from evaluated object, so that all the data needed for hair matrix is
+ * present. */
+static void hair_key_location_object_set(HairKey *hair_key,
+ Object *object,
+ ParticleSystemModifierData *modifier,
+ ParticleData *particle,
+ const float src_co[3])
+{
+ Mesh *hair_mesh = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_mesh :
+ NULL;
+
+ if (hair_mesh != NULL) {
+ const int hair_key_index = hair_key_index_get(hair_key, modifier, particle);
+ if (hair_key_index == -1) {
+ return;
+ }
+
+ MVert *mvert = &hair_mesh->mvert[particle->hair_index + (hair_key_index)];
+ copy_v3_v3(mvert->co, src_co);
+ return;
+ }
+
+ float hairmat[4][4];
+ psys_mat_hair_to_object(
+ object, modifier->mesh_final, modifier->psys->part->from, particle, hairmat);
+
+ float imat[4][4];
+ invert_m4_m4(imat, hairmat);
+
+ copy_v3_v3(hair_key->co, src_co);
+ mul_m4_v3(imat, hair_key->co);
+}
+
static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values)
{
HairKey *hkey = (HairKey *)ptr->data;
Object *ob = (Object *)ptr->owner_id;
+
ParticleSystemModifierData *psmd;
ParticleData *pa;
-
rna_ParticleHairKey_location_object_info(ptr, &psmd, &pa);
- if (pa) {
- Mesh *hair_mesh = (psmd->psys->flag & PSYS_HAIR_DYNAMICS) ? psmd->psys->hair_out_mesh : NULL;
-
- if (hair_mesh) {
- MVert *mvert = &hair_mesh->mvert[pa->hair_index + (hkey - pa->hair)];
- copy_v3_v3(mvert->co, values);
- }
- else {
- float hairmat[4][4];
- float imat[4][4];
-
- psys_mat_hair_to_object(ob, psmd->mesh_final, psmd->psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
- copy_v3_v3(hkey->co, values);
- mul_m4_v3(imat, hkey->co);
- }
- }
- else {
+ if (pa == NULL) {
zero_v3(hkey->co);
+ return;
}
+
+ hair_key_location_object_set(hkey, ob, psmd, pa, values);
}
static void rna_ParticleHairKey_co_object(HairKey *hairkey,
@@ -301,6 +353,31 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey,
}
}
+static void rna_ParticleHairKey_co_object_set(ID *id,
+ HairKey *hair_key,
+ Object *object,
+ ParticleSystemModifierData *modifier,
+ ParticleData *particle,
+ float co[3])
+{
+
+ if (particle == NULL) {
+ return;
+ }
+
+ /* Mark particle system as edited, so then particle_system_update() does not reset the hair
+ * keys from path. This behavior is similar to how particle edit mode sets flags. */
+ ParticleSystemModifierData *orig_modifier = (ParticleSystemModifierData *)
+ modifier->modifier.orig_modifier_data;
+ orig_modifier->psys->flag |= PSYS_EDITED;
+
+ hair_key_location_object_set(hair_key, object, modifier, particle, co);
+
+ /* Tag similar to brushes in particle edit mode, so the modifier stack is properly evaluated
+ * with the same particle system recalc flags as during combing. */
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
+}
+
static void rna_Particle_uv_on_emitter(ParticleData *particle,
ReportList *reports,
ParticleSystemModifierData *modifier,
@@ -1651,6 +1728,19 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Exported hairkey location", -1e4, 1e4);
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
RNA_def_function_output(func, parm);
+
+ func = RNA_def_function(srna, "co_object_set", "rna_ParticleHairKey_co_object_set");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Set hairkey location with particle and modifier data");
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "particle", "Particle", "", "hair particle");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_float_vector(
+ func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Specified hairkey location", -1e4, 1e4);
+ RNA_def_parameter_flags(parm, PROP_THICK_WRAP, PARM_REQUIRED);
}
static void rna_def_particle_key(BlenderRNA *brna)
@@ -3019,7 +3109,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
/* physical properties */
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS);
RNA_def_property_range(prop, 0.00000001f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01, 100, 1, 3);
+ RNA_def_property_ui_range(prop, 0.01, 100, 1, 4);
RNA_def_property_ui_text(prop, "Mass", "Mass of the particles");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
@@ -3349,7 +3439,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "keyed_loops", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "keyed_loops");
RNA_def_property_range(prop, 1.0f, 10000.0f);
- RNA_def_property_ui_range(prop, 1.0f, 100.0f, 0.1, 3);
+ RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
RNA_def_property_ui_text(prop, "Loop Count", "Number of times the keys are looped");
RNA_def_property_update(prop, 0, "rna_Particle_redo");