Fix T60132: Convert hair particles to mesh

Needed to port operator to use evaluated particle system.

But also changed interface to always show Convert button when
draw type is set to Path (Hair particle system is forced to
be draws as path). This avoid rather expensive lookup on every
redraw, but will show Convert button for un-baked particle
emitter.

Probably, an acceptable compromise.
This commit is contained in:
Sergey Sharybin 2019-01-04 14:28:47 +01:00
parent 1753177ad8
commit 2c21e3e35f
Notes: blender-bot 2023-02-14 07:47:59 +01:00
Referenced by issue #60447, Weird behavior with texture and brush
Referenced by issue #60239, Proportional editing acting weirdly - Only half of the shape is reacting to it.
Referenced by issue #60171, Hair Particles Not Displaying in Viewport
Referenced by issue #60132, convert hair particles to mesh
Referenced by issue #58489, Particle edit mode crash on macOS + NVIDIA
Referenced by issue #58233, Crash selecting path as render as type in particle system.
6 changed files with 55 additions and 34 deletions

View File

@ -303,7 +303,19 @@ void psys_set_current_num(Object *ob, int index);
struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
/* For a given evaluated particle system get its original.
*
* If this input is an original particle system already, the return value is the
* same as the input. */
struct ParticleSystem *psys_orig_get(struct ParticleSystem *psys);
/* For a given original object and its particle system, get evaluated particle
* system within a given dependency graph. */
struct ParticleSystem *psys_eval_get(struct Depsgraph *depsgraph,
struct Object *object,
struct ParticleSystem *psys);
bool psys_in_edit_mode(struct Depsgraph *depsgraph, const struct ParticleSystem *psys);
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
bool psys_check_edited(struct ParticleSystem *psys);

View File

@ -282,6 +282,24 @@ ParticleSystem *psys_orig_get(ParticleSystem *psys)
return psys->orig_psys;
}
struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph,
Object *object,
ParticleSystem *psys)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
if (object_eval == object) {
return psys;
}
ParticleSystem *psys_eval = object_eval->particlesystem.first;
while (psys_eval != NULL) {
if (psys_eval->orig_psys == psys) {
return psys_eval;
}
psys_eval = psys_eval->next;
}
return psys_eval;
}
static PTCacheEdit *psys_orig_edit_get(ParticleSystem *psys)
{
if (psys->orig_psys == NULL) {

View File

@ -248,7 +248,7 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_convert(
struct ReportList *reports, struct Main *bmain, struct Scene *scene,
struct ReportList *reports, struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene,
struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_apply(
struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene,

View File

@ -1507,12 +1507,14 @@ static uiLayout *draw_modifier(
ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
"OBJECT_OT_duplicates_make_real");
else if (psys->part->ren_as == PART_DRAW_PATH && psys->pathcache)
}
else if (psys->part->ren_as == PART_DRAW_PATH) {
uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
"OBJECT_OT_modifier_convert");
}
}
}
else {

View File

@ -432,10 +432,12 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *
return 1;
}
int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, ModifierData *md)
int ED_object_modifier_convert(ReportList *UNUSED(reports),
Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer,
Object *ob, ModifierData *md)
{
Object *obn;
ParticleSystem *psys;
ParticleSystem *psys_orig, *psys_eval;
ParticleCacheKey *key, **cache;
ParticleSettings *part;
Mesh *me;
@ -448,20 +450,25 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
if (md->type != eModifierType_ParticleSystem) return 0;
if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
psys = ((ParticleSystemModifierData *)md)->psys;
part = psys->part;
psys_orig = ((ParticleSystemModifierData *)md)->psys;
part = psys_orig->part;
if (part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
if (part->ren_as != PART_DRAW_PATH) {
return 0;
}
psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
if (psys_eval->pathcache == NULL) {
return 0;
}
totpart = psys->totcached;
totchild = psys->totchildcache;
totpart = psys_eval->totcached;
totchild = psys_eval->totchildcache;
if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
totpart = 0;
/* count */
cache = psys->pathcache;
cache = psys_eval->pathcache;
for (a = 0; a < totpart; a++) {
key = cache[a];
@ -471,7 +478,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
}
}
cache = psys->childcache;
cache = psys_eval->childcache;
for (a = 0; a < totchild; a++) {
key = cache[a];
@ -498,7 +505,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
medge = me->medge;
/* copy coordinates */
cache = psys->pathcache;
cache = psys_eval->pathcache;
for (a = 0; a < totpart; a++) {
key = cache[a];
kmax = key->segments;
@ -517,7 +524,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
}
}
cache = psys->childcache;
cache = psys_eval->childcache;
for (a = 0; a < totchild; a++) {
key = cache[a];
kmax = key->segments;
@ -1086,12 +1093,13 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
static int modifier_convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, view_layer, ob, md))
if (!md || !ED_object_modifier_convert(op->reports, bmain, depsgraph, scene, view_layer, ob, md))
return OPERATOR_CANCELLED;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);

View File

@ -4650,25 +4650,6 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
static struct ParticleSystem *psys_eval_get(
Depsgraph *depsgraph,
Object *object,
ParticleSystem *psys)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
if (object_eval == object) {
return psys;
}
ParticleSystem *psys_eval = object_eval->particlesystem.first;
while (psys_eval != NULL) {
if (psys_eval->orig_psys == psys) {
return psys_eval;
}
psys_eval = psys_eval->next;
}
return psys_eval;
}
/* initialize needed data for bake edit */
void PE_create_particle_edit(
Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)