Fix T60132: Convert hair particles to mesh
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 4 Jan 2019 13:28:47 +0000 (14:28 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 4 Jan 2019 13:30:34 +0000 (14:30 +0100)
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.

source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/particle.c
source/blender/editors/include/ED_object.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_modifier.c
source/blender/editors/physics/particle_edit.c

index cf123f78ae02a312cdd06d3625faeba13cc1d198..5a1241f1de263db5bdea5e5fc92f48db362a79c1 100644 (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);
index 7f3bae9d178321e2d623bc9e1b0d169fb6ccf985..3b61c47cb4341da760b0a5829f7008f39d0150f1 100644 (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) {
index fd0635e31ef70b8019413ce5dd09c59d50723de6..7f7e74a4e4ec161d569affdcf152faa3cc2e8ee9 100644 (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,
index ec055ddb05bec202585fb072f8a65f4e02d73ca1..d7e3dbf6e320daa495ef12cb10a51053dd19065b 100644 (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 {
index 15aca6a325394c2cbd7ca5e41fe1d58289c79eee..79dffa17c7ad2d574894981e4bcf4dd3941ee07f 100644 (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);
index 33ed333635560f844fa0a7b664dbfaa1da04ec05..e8afa1ae44197246b985e599ed93c2014c748046 100644 (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)