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:
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.
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue