From 63225d7c8b3a45e8189476d537585b011993fb17 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 18 Apr 2018 12:14:28 +0200 Subject: [PATCH 1/2] Port particle instance modifier changes from Gooseberry branch The work is mainly from Lukas Toenne, with some modifications from myself. Includes following obvious changes: - Particle system selection is now name-based, with lookup menu. - Lots of new options to control varieties. Changes comparing to the Gooseberry branch: - Default values and versioning code ensures same behavior as the old modifier. - Custom data layers are coming from vertex color, the modifier does not create arbitrary layers now. The hope is to keep data more manageable, and maybe make it easier to select in the shader later on. This means, values are quantized to 256 values, but it should be enough to get varieties in practice. Reviewers: brecht, campbellbarton Reviewed By: brecht Subscribers: eyecandy Differential Revision: https://developer.blender.org/D3157 --- .../startup/bl_ui/properties_data_modifier.py | 22 +- .../blenloader/intern/versioning_270.c | 12 ++ source/blender/makesdna/DNA_modifier_types.h | 11 +- source/blender/makesrna/intern/rna_modifier.c | 95 ++++++++- .../modifiers/intern/MOD_particleinstance.c | 191 ++++++++++++++---- 5 files changed, 281 insertions(+), 50 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 942882a9053..e3cc08ce3d8 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -711,11 +711,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): def PARTICLE_INSTANCE(self, layout, ob, md): layout.prop(md, "object") - layout.prop(md, "particle_system_index", text="Particle System") + if md.object: + layout.prop_search(md, "particle_system", md.object, "particle_systems", text="Particle System") + else: + layout.prop(md, "particle_system_index", text="Particle System") split = layout.split() col = split.column() col.label(text="Create From:") + layout.prop(md, "space", text="") col.prop(md, "use_normal") col.prop(md, "use_children") col.prop(md, "use_size") @@ -726,6 +730,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "show_unborn") col.prop(md, "show_dead") + row = layout.row(align=True) + row.prop(md, "particle_amount", text="Amount") + row.prop(md, "particle_offset", text="Offset") + layout.separator() layout.prop(md, "use_path", text="Create Along Paths") @@ -737,8 +745,16 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "use_preserve_shape") col = split.column() - col.prop(md, "position", slider=True) - col.prop(md, "random_position", text="Random", slider=True) + col2 = col.column(align=True) + col2.prop(md, "position", slider=True) + col2.prop(md, "random_position", text="Random", slider=True) + col2 = col.column(align=True) + col2.prop(md, "rotation", slider=True) + col2.prop(md, "random_rotation", text="Random", slider=True) + + col = layout.column() + col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer") + col.prop_search(md, "value_layer_name", ob.data, "vertex_colors", text="Value Layer") def PARTICLE_SYSTEM(self, layout, ob, md): layout.label(text="Settings can be found inside the Particle context") diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index e9de7919d25..86e6071180e 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1813,6 +1813,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } scene->r.ffcodecdata.ffmpeg_preset = preset; } + + if (!DNA_struct_elem_find(fd->filesdna, "ParticleInstanceModifierData", "float", "particle_amount")) { + for (Object *ob = main->object.first; ob; ob = ob->id.next) { + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_ParticleInstance) { + ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; + pimd->space = eParticleInstanceSpace_World; + pimd->particle_amount = 1.0f; + } + } + } + } } } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 766dd196562..258acbab31a 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -753,12 +753,21 @@ typedef enum { eParticleInstanceFlag_UseSize = (1 << 7), } ParticleInstanceModifierFlag; +typedef enum { + eParticleInstanceSpace_World = 0, + eParticleInstanceSpace_Local = 1, +} ParticleInstanceModifierSpace; + typedef struct ParticleInstanceModifierData { ModifierData modifier; struct Object *ob; - short psys, flag, axis, pad; + short psys, flag, axis, space; float position, random_position; + float rotation, random_rotation; + float particle_amount, particle_offset; + char index_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char value_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ } ParticleInstanceModifierData; typedef enum { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 2f92c47eed9..0ebd29b200c 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1155,6 +1155,43 @@ static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, rna_Modifier_update(bmain, scene, ptr); } +static int rna_ParticleInstanceModifier_particle_system_poll(PointerRNA *ptr, const PointerRNA value) +{ + ParticleInstanceModifierData *psmd = ptr->data; + ParticleSystem *psys = value.data; + + if (!psmd->ob) + return false; + + /* make sure psys is in the object */ + return BLI_findindex(&psmd->ob->particlesystem, psys) >= 0; +} + +static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *ptr) +{ + ParticleInstanceModifierData *psmd = ptr->data; + ParticleSystem *psys; + PointerRNA rptr; + + if (!psmd->ob) + return PointerRNA_NULL; + + psys = BLI_findlink(&psmd->ob->particlesystem, psmd->psys - 1); + RNA_pointer_create((ID *)psmd->ob, &RNA_ParticleSystem, psys, &rptr); + return rptr; +} + +static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, const PointerRNA value) +{ + ParticleInstanceModifierData *psmd = ptr->data; + + if (!psmd->ob) + return; + + psmd->psys = BLI_findindex(&psmd->ob->particlesystem, value.data) + 1; + CLAMP_MIN(psmd->psys, 1); +} + #else static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[]) @@ -2655,6 +2692,12 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem particleinstance_space[] = { + {eParticleInstanceSpace_Local, "LOCAL", 0, "Local", "Use offset from the particle object in the instance object"}, + {eParticleInstanceSpace_World, "WORLD", 0, "World", "Use world space offset in the instance object"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "ParticleInstanceModifier", "Modifier"); RNA_def_struct_ui_text(srna, "ParticleInstance Modifier", "Particle system instancing modifier"); RNA_def_struct_sdna(srna, "ParticleInstanceModifierData"); @@ -2669,16 +2712,30 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "psys"); - RNA_def_property_range(prop, 1, 10); + RNA_def_property_range(prop, 1, SHRT_MAX); RNA_def_property_ui_text(prop, "Particle System Number", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ParticleSystem"); + RNA_def_property_pointer_funcs(prop, "rna_ParticleInstanceModifier_particle_system_get", "rna_ParticleInstanceModifier_particle_system_set", + NULL, "rna_ParticleInstanceModifier_particle_system_poll"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Particle System", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "axis"); RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items); RNA_def_property_ui_text(prop, "Axis", "Pole axis for rotation"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + + prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "space"); + RNA_def_property_enum_items(prop, particleinstance_space); + RNA_def_property_ui_text(prop, "Space", "Space to use for copying mesh data"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Parents); RNA_def_property_ui_text(prop, "Normal", "Create instances from normal particles"); @@ -2730,6 +2787,40 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_ui_text(prop, "Random Position", "Randomize position along path"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "rotation"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Rotation", "Rotation around path"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_rotation"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Random Rotation", "Randomize rotation around path"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "particle_amount", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Particle Amount", "Amount of particles to use for instancing"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "particle_offset", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Particle Offset", "Relative offset of particles to use for instancing, to avoid overlap of multiple instances"); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "index_layer_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "index_layer_name"); + RNA_def_property_ui_text(prop, "Index Layer Name", "Custom data layer name for the index"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "value_layer_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "value_layer_name"); + RNA_def_property_ui_text(prop, "Value Layer Name", "Custom data layer name for the randomized value"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_explode(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 106a84d3765..f0b80cda447 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -40,10 +40,12 @@ #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_rand.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_effect.h" +#include "BKE_global.h" #include "BKE_lattice.h" #include "BKE_library_query.h" #include "BKE_modifier.h" @@ -53,8 +55,6 @@ #include "depsgraph_private.h" #include "DEG_depsgraph_build.h" -#include "MOD_modifiertypes.h" - static void initData(ModifierData *md) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; @@ -64,7 +64,12 @@ static void initData(ModifierData *md) pimd->psys = 1; pimd->position = 1.0f; pimd->axis = 2; + pimd->space = eParticleInstanceSpace_World; + pimd->particle_amount = 1.0f; + pimd->particle_offset = 0.0f; + STRNCPY(pimd->index_layer_name, ""); + STRNCPY(pimd->value_layer_name, ""); } static void copyData(ModifierData *md, ModifierData *target) { @@ -75,6 +80,21 @@ static void copyData(ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); } +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) +{ + ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; + CustomDataMask dataMask = 0; + + if (pimd->index_layer_name[0] != '\0' || + pimd->value_layer_name[0] != '\0') + { + dataMask |= CD_MASK_MLOOPCOL; + } + + return dataMask; + +} + static bool isDisabled(ModifierData *md, int useRenderParams) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; @@ -142,39 +162,59 @@ static void foreachObjectLink(ModifierData *md, Object *ob, walk(userData, ob, &pimd->ob, IDWALK_CB_NOP); } -static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) +static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) { + const bool between = (psys->part->childtype == PART_CHILD_FACES); ParticleData *pa; + int totpart, randp, minp, maxp; - if (pimd->flag & eParticleInstanceFlag_Parents) { - if (p >= psys->totpart) { - if (psys->part->childtype == PART_CHILD_PARTICLES) { - pa = psys->particles + (psys->child + p - psys->totpart)->parent; - } - else { - pa = NULL; - } - } - else { - pa = psys->particles + p; - } + if (p >= psys->totpart) { + ChildParticle *cpa = psys->child + (p - psys->totpart); + pa = psys->particles + (between? cpa->pa[0]: cpa->parent); } else { - if (psys->part->childtype == PART_CHILD_PARTICLES) { - pa = psys->particles + (psys->child + p)->parent; - } - else { - pa = NULL; - } + pa = psys->particles + p; } if (pa) { - if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1; - if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1; - if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1; + if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true; + if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true; + if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true; } - return 0; + if (pimd->particle_amount == 1.0f) { + /* Early output, all particles are to be instanced. */ + return false; + } + + /* Randomly skip particles based on desired amount of visible particles. */ + + totpart = psys->totpart + psys->totchild; + + /* TODO make randomization optional? */ + randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart; + + minp = (int)(totpart * pimd->particle_offset) % (totpart+1); + maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart+1); + + if (maxp > minp) { + return randp < minp || randp >= maxp; + } + else if (maxp < minp) { + return randp < minp && randp >= maxp; + } + else { + return true; + } + + return false; +} + +static void store_float_in_vcol(MLoopCol *vcol, float float_value) +{ + const uchar value = FTOCHAR(float_value); + vcol->r = vcol->g = vcol->b = value; + vcol->a = 1.0f; } static DerivedMesh *applyModifier(ModifierData *md, Object *ob, @@ -190,11 +230,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, MLoop *mloop, *orig_mloop; MVert *mvert, *orig_mvert; int totvert, totpoly, totloop /* , totedge */; - int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0; + int maxvert, maxpoly, maxloop, part_end = 0, part_start; int k, p, p_skip; short track = ob->trackflag % 3, trackneg, axis = pimd->axis; float max_co = 0.0, min_co = 0.0, temp_co[3]; float *size = NULL; + float spacemat[4][4]; + const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents; + const bool use_children = pimd->flag & eParticleInstanceFlag_Children; + bool between; trackneg = ((ob->trackflag > 2) ? 1 : 0); @@ -212,25 +256,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, return derivedData; } - if (pimd->flag & eParticleInstanceFlag_Parents) - totpart += psys->totpart; - if (pimd->flag & eParticleInstanceFlag_Children) { - if (totpart == 0) - first_particle = psys->totpart; - totpart += psys->totchild; - } + part_start = use_parents ? 0 : psys->totpart; - if (totpart == 0) + part_end = 0; + if (use_parents) + part_end += psys->totpart; + if (use_children) + part_end += psys->totchild; + + if (part_end == 0) return derivedData; sim.scene = md->scene; sim.ob = pimd->ob; sim.psys = psys; sim.psmd = psys_get_modifier(pimd->ob, psys); + between = (psys->part->childtype == PART_CHILD_FACES); if (pimd->flag & eParticleInstanceFlag_UseSize) { float *si; - si = size = MEM_calloc_arrayN(totpart, sizeof(float), "particle size array"); + si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array"); if (pimd->flag & eParticleInstanceFlag_Parents) { for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) @@ -246,6 +291,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } } + switch (pimd->space) { + case eParticleInstanceSpace_World: + /* particle states are in world space already */ + unit_m4(spacemat); + break; + case eParticleInstanceSpace_Local: + /* get particle states in the particle object's local space */ + invert_m4_m4(spacemat, pimd->ob->obmat); + break; + default: + /* should not happen */ + BLI_assert(false); + break; + } + totvert = dm->getNumVerts(dm); totpoly = dm->getNumPolys(dm); totloop = dm->getNumLoops(dm); @@ -256,7 +316,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, maxpoly = 0; maxloop = 0; - for (p = 0; p < totpart; p++) { + for (p = part_start; p < part_end; p++) { if (particle_skip(pimd, psys, p)) continue; @@ -285,9 +345,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mloop = result->getLoopArray(result); orig_mloop = dm->getLoopArray(dm); - for (p = 0, p_skip = 0; p < totpart; p++) { + MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->index_layer_name); + MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->value_layer_name); + int *vert_part_index = NULL; + float *vert_part_value = NULL; + if (mloopcols_index != NULL) { + vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array"); + } + if (mloopcols_value) { + vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array"); + } + + for (p = part_start, p_skip = 0; p < part_end; p++) { float prev_dir[3]; float frame[4]; /* frame orientation quaternion */ + float p_random = psys_frand(psys, 77091 + 283*p); /* skip particle? */ if (particle_skip(pimd, psys, p)) @@ -297,12 +369,20 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for (k = 0; k < totvert; k++) { ParticleKey state; MVert *inMV; - MVert *mv = mvert + p_skip * totvert + k; + int vindex = p_skip * totvert + k; + MVert *mv = mvert + vindex; inMV = orig_mvert + k; DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1); *mv = *inMV; + if (vert_part_index != NULL) { + vert_part_index[vindex] = p; + } + if (vert_part_value != NULL) { + vert_part_value[vindex] = p_random; + } + /*change orientation based on object trackflag*/ copy_v3_v3(temp_co, mv->co); mv->co[axis] = temp_co[track]; @@ -330,7 +410,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mv->co[axis] = 0.0; } - psys_get_particle_on_path(&sim, first_particle + p, &state, 1); + psys_get_particle_on_path(&sim, p, &state, 1); normalize_v3(state.vel); @@ -339,17 +419,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, float hairmat[4][4]; float mat[3][3]; - if (first_particle + p < psys->totpart) - pa = psys->particles + first_particle + p; + if (p < psys->totpart) + pa = psys->particles + p; else { ChildParticle *cpa = psys->child + (p - psys->totpart); - pa = psys->particles + cpa->parent; + pa = psys->particles + (between? cpa->pa[0]: cpa->parent); } psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat); copy_m3_m4(mat, hairmat); /* to quaternion */ mat3_to_quat(frame, mat); + if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) { + float angle = 2.0f*M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f)); + float eul[3] = { 0.0f, 0.0f, angle }; + float rot[4]; + + eul_to_quat(rot, eul); + mul_qt_qtqt(frame, frame, rot); + } + /* note: direction is same as normal vector currently, * but best to keep this separate so the frame can be * rotated later if necessary @@ -386,13 +475,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } else { state.time = -1.0; - psys_get_particle_state(&sim, first_particle + p, &state, 1); + psys_get_particle_state(&sim, p, &state, 1); } mul_qt_v3(state.rot, mv->co); if (pimd->flag & eParticleInstanceFlag_UseSize) mul_v3_fl(mv->co, size[p]); add_v3_v3(mv->co, state.co); + + mul_m4_v3(spacemat, mv->co); } /* create polys and loops */ @@ -412,6 +503,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j); for (; j; j--, ml++, inML++) { ml->v = inML->v + (p_skip * totvert); + const int ml_index = (ml - mloop); + if (mloopcols_index != NULL) { + const int part_index = vert_part_index[ml->v]; + store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / psys->totpart); + } + if (mloopcols_value != NULL) { + const float part_value = vert_part_value[ml->v]; + store_float_in_vcol(&mloopcols_value[ml_index], part_value); + } } } } @@ -429,6 +529,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (size) MEM_freeN(size); + MEM_SAFE_FREE(vert_part_index); + MEM_SAFE_FREE(vert_part_value); + result->dirty |= DM_DIRTY_NORMALS; return result; @@ -451,7 +554,7 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, /* initData */ initData, - /* requiredDataMask */ NULL, + /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, From da82269c58bd7ec1c0ebcb5e1433c731120ec389 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Apr 2018 12:52:32 +0200 Subject: [PATCH 2/2] Cleanup: rename Icon.type -> id_type Confusing when adding non-id icons. --- source/blender/blenkernel/BKE_icons.h | 3 ++- source/blender/blenkernel/intern/icons.c | 8 ++++---- source/blender/editors/interface/interface_icons.c | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index c3f5d7bf7c2..686dba21283 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -39,7 +39,8 @@ typedef void (*DrawInfoFreeFP)(void *drawinfo); struct Icon { void *drawinfo; void *obj; - short type; + /** #ID_Type or 0 when not used for ID preview. */ + short id_type; DrawInfoFreeFP drawinfo_free; }; diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 6aa00b2c97d..3ac8abd55f6 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -475,7 +475,7 @@ void BKE_icon_changed(const int icon_id) if (icon) { /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ - BLI_assert(icon->type != 0); + BLI_assert(icon->id_type != 0); /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here , * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */ @@ -501,7 +501,7 @@ static int icon_id_ensure_create_icon(struct ID *id) new_icon = MEM_mallocN(sizeof(Icon), __func__); new_icon->obj = id; - new_icon->type = GS(id->name); + new_icon->id_type = GS(id->name); /* next two lines make sure image gets created */ new_icon->drawinfo = NULL; @@ -577,7 +577,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) new_icon = MEM_mallocN(sizeof(Icon), __func__); new_icon->obj = preview; - new_icon->type = 0; /* Special, tags as non-ID icon/preview. */ + new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */ /* next two lines make sure image gets created */ new_icon->drawinfo = NULL; @@ -654,7 +654,7 @@ void BKE_icon_delete(const int icon_id) icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); if (icon) { - if (icon->type) { + if (icon->id_type != 0) { ((ID *)(icon->obj))->icon_id = 0; } else { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 62244979c12..ed57412c05c 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -139,7 +139,7 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, new_icon = MEM_callocN(sizeof(Icon), "texicon"); new_icon->obj = NULL; /* icon is not for library object */ - new_icon->type = 0; + new_icon->id_type = 0; di = MEM_callocN(sizeof(DrawInfo), "drawinfo"); di->type = type; @@ -191,7 +191,7 @@ static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc) new_icon = MEM_callocN(sizeof(Icon), "texicon"); new_icon->obj = NULL; /* icon is not for library object */ - new_icon->type = 0; + new_icon->id_type = 0; di = MEM_callocN(sizeof(DrawInfo), "drawinfo"); di->type = ICON_TYPE_VECTOR; @@ -849,7 +849,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi switch (di->type) { case ICON_TYPE_PREVIEW: { - ID *id = (icon->type != 0) ? icon->obj : NULL; + ID *id = (icon->id_type != 0) ? icon->obj : NULL; PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj; if (prv) { @@ -905,7 +905,7 @@ PreviewImage *UI_icon_to_preview(int icon_id) DrawInfo *di = (DrawInfo *)icon->drawinfo; if (di) { if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; + PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; if (prv) { return BKE_previewimg_copy(prv); @@ -1124,7 +1124,7 @@ static void icon_draw_size( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; + PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; if (pi) { /* no create icon on this level in code */