diff options
21 files changed, 215 insertions, 69 deletions
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 0c29c606df8..6564eea4767 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -469,6 +469,7 @@ static bool object_render_hide(BL::Object& b_ob, BL::Object::particle_systems_iterator b_psys; bool hair_present = false; + bool has_particles = false; bool show_emitter = false; bool hide_emitter = false; bool hide_as_dupli_parent = false; @@ -478,20 +479,17 @@ static bool object_render_hide(BL::Object& b_ob, if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) && (b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) hair_present = true; - - if(b_psys->settings().use_render_emitter()) - show_emitter = true; - else - hide_emitter = true; + has_particles = true; } - if(show_emitter) - hide_emitter = false; - - /* duplicators hidden by default, except dupliframes which duplicate self */ - if(b_ob.is_duplicator()) - if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES) + if(has_particles) { + show_emitter = b_ob.show_duplicator_for_render(); + hide_emitter = !show_emitter; + } else if(b_ob.is_duplicator()) { + if(top_level || b_ob.show_duplicator_for_render()) { hide_as_dupli_parent = true; + } + } /* hide original object for duplis */ BL::Object parent = b_ob.parent(); diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 23787756121..de608c42cb5 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -278,6 +278,13 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): col.label(text="Object Color:") col.prop(obj, "color", text="") + col = layout.column() + col.active = bool(is_dupli or obj.particle_systems) + col.label(text="Duplicator Visibility:") + row = col.row(align=True) + row.prop(obj, "show_duplicator_for_viewport", text="Viewport") + row.prop(obj, "show_duplicator_for_render", text="Render") + class OBJECT_PT_duplication(ObjectButtonsPanel, Panel): bl_label = "Duplication" diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index a5793e6d9a9..fda3096a3f5 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -926,7 +926,6 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): split = layout.split() col = split.column() - col.prop(part, "use_render_emitter") col.prop(part, "use_parent_particles") col = split.column() diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 2b183906f57..d98c52aa91a 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -82,7 +82,14 @@ bool BKE_object_exists_check(struct Object *obtest); bool BKE_object_is_in_editmode(struct Object *ob); bool BKE_object_is_in_editmode_vgroup(struct Object *ob); bool BKE_object_is_in_wpaint_select_vert(struct Object *ob); -bool BKE_object_is_visible(struct Object *ob); + +typedef enum eObjectVisibilityCheck { + OB_VISIBILITY_CHECK_FOR_VIEWPORT, + OB_VISIBILITY_CHECK_FOR_RENDER, + OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE, +} eObjectVisibilityCheck; + +bool BKE_object_is_visible(struct Object *ob, const eObjectVisibilityCheck mode); void BKE_object_init(struct Object *ob); struct Object *BKE_object_add_only_object( diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 66c87ac7a5c..923cea6acff 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -552,11 +552,32 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob) /** * Return if the object is visible, as evaluated by depsgraph - * Keep in sync with rna_object.c (object.is_visible). */ -bool BKE_object_is_visible(Object *ob) +bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode) { - return (ob->base_flag & BASE_VISIBLED) != 0; + if ((ob->base_flag & BASE_VISIBLED) == 0) { + return false; + } + + if (mode == OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) { + return true; + } + + if (((ob->transflag & OB_DUPLI) == 0) && + (ob->particlesystem.first == NULL)) + { + return true; + } + + switch (mode) { + case OB_VISIBILITY_CHECK_FOR_VIEWPORT: + return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT) != 0); + case OB_VISIBILITY_CHECK_FOR_RENDER: + return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0); + default: + BLI_assert(!"Object visible test mode not supported."); + return false; + } } bool BKE_object_exists_check(Object *obtest) @@ -684,6 +705,7 @@ void BKE_object_init(Object *ob) ob->col_group = 0x01; ob->col_mask = 0xffff; ob->preview = NULL; + ob->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER; /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index a161dd4fac3..77c648e53fe 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3279,7 +3279,7 @@ static void default_particle_settings(ParticleSettings *part) part->clength = 1.0f; part->clength_thres = 0.0f; - part->draw = PART_DRAW_EMITTER; + part->draw = 0; part->draw_line[0] = 0.5; part->path_start = 0.0f; part->path_end = 1.0f; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 944ddf1763d..547ae6709b2 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -45,6 +45,7 @@ #include "DNA_lightprobe_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" @@ -855,4 +856,28 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + { + if (!DNA_struct_elem_find(fd->filesdna, "Object", "char", "duplicator_visibility_flag")) { + for (Object *object = main->object.first; object; object = object->id.next) { + if (object->particlesystem.first) { + bool show_emitter = false; + for (ParticleSystem *psys = object->particlesystem.first; psys; psys=psys->next) { + show_emitter |= (psys->part->draw & PART_DRAW_EMITTER) != 0; + } + + object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT; + if (show_emitter) { + object->duplicator_visibility_flag |= OB_DUPLI_FLAG_RENDER; + } + } + else if (object->transflag & OB_DUPLI){ + object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT; + } + else { + object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER; + } + } + } + } } diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index c782a91f76e..83fb100436c 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -77,12 +77,18 @@ enum { DEG_ITER_OBJECT_FLAG_DUPLI = (1 << 4), }; +typedef enum eDepsObjectIteratorMode { + DEG_ITER_OBJECT_MODE_VIEWPORT = 0, + DEG_ITER_OBJECT_MODE_RENDER = 1, +} eDepsObjectIteratorMode; + typedef struct DEGObjectIterData { struct Depsgraph *graph; struct Scene *scene; struct EvaluationContext eval_ctx; int flag; + eDepsObjectIteratorMode mode; /* **** Iteration over dupli-list. *** */ @@ -115,10 +121,11 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter); * Although they are available they have no overrides (collection_properties) * and will crash if you try to access it. */ -#define DEG_OBJECT_ITER(graph_, instance_, flag_) \ +#define DEG_OBJECT_ITER(graph_, instance_, mode_, flag_) \ { \ DEGObjectIterData data_ = { \ .graph = (graph_), \ + .mode = (mode_), \ .flag = (flag_), \ }; \ \ @@ -134,8 +141,8 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter); /** * Depsgraph objects iterator for draw manager and final render */ -#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph_, instance_) \ - DEG_OBJECT_ITER(graph_, instance_, \ +#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph_, instance_, mode_) \ + DEG_OBJECT_ITER(graph_, instance_, mode_, \ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | \ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | \ DEG_ITER_OBJECT_FLAG_VISIBLE | \ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 2a323fe63bd..42d512d473c 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -84,6 +84,7 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) Object *dupli_parent = data->dupli_parent; Object *temp_dupli_object = &data->temp_dupli_object; *temp_dupli_object = *dob->ob; + temp_dupli_object->transflag &= ~OB_DUPLI; temp_dupli_object->select_color = dupli_parent->select_color; temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI; @@ -139,7 +140,7 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no Object *object = (Object *)id_node->id_cow; BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id)); - if ((BKE_object_is_visible(object) == false) && + if ((BKE_object_is_visible(object, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) == false) && ((data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) != 0)) { return; @@ -149,6 +150,14 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no data->dupli_parent = object; data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object); data->dupli_object_next = (DupliObject *)data->dupli_list->first; + + const eObjectVisibilityCheck mode = (data->mode == DEG_ITER_OBJECT_MODE_RENDER) ? + OB_VISIBILITY_CHECK_FOR_RENDER : + OB_VISIBILITY_CHECK_FOR_VIEWPORT; + + if (BKE_object_is_visible(object, mode) == false) { + return; + } } iter->current = object; @@ -167,7 +176,10 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) } /* TODO(sergey): What evaluation type we want here? */ - DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_RENDER); + /* TODO(dfelinto): Get rid of evaluation context here, it's only used to do + * direct dupli-objects update in group.c. Which is terribly bad, and all + * objects are expected to be evaluated already. */ + DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_VIEWPORT); data->eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph); iter->data = data; @@ -193,6 +205,7 @@ void DEG_iterator_objects_next(BLI_Iterator *iter) Depsgraph *depsgraph = data->graph; DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); do { + iter->skip = false; if (data->dupli_list) { if (deg_objects_dupli_iterator_next(iter)) { return; diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index 01f89ae6b1c..9f9ebd692b9 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -746,12 +746,45 @@ static void clay_cache_init(void *vedata) } } +static void clay_cache_populate_particles(void *vedata, Object *ob) +{ + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + + Scene *scene = draw_ctx->scene; + Object *obedit = scene->obedit; + + if (ob != obedit) { + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (psys_check_enabled(ob, psys, false)) { + ParticleSettings *part = psys->part; + int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) { + draw_as = PART_DRAW_DOT; + } + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_hair(psys, NULL); + DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); + DRW_shgroup_call_add(hair_shgrp, geom, mat); + } + } + } + } +} + static void clay_cache_populate(void *vedata, Object *ob) { CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - DRWShadingGroup *clay_shgrp, *hair_shgrp; + DRWShadingGroup *clay_shgrp; if (!DRW_object_is_renderable(ob)) return; @@ -764,6 +797,15 @@ static void clay_cache_populate(void *vedata, Object *ob) } } + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob->type == OB_MESH) { + clay_cache_populate_particles(vedata, ob); + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, ""); @@ -797,33 +839,6 @@ static void clay_cache_populate(void *vedata, Object *ob) DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); } } - - if (ob->type == OB_MESH) { - Scene *scene = draw_ctx->scene; - Object *obedit = scene->obedit; - - if (ob != obedit) { - for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { - if (psys_check_enabled(ob, psys, false)) { - ParticleSettings *part = psys->part; - int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - - if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) { - draw_as = PART_DRAW_DOT; - } - - static float mat[4][4]; - unit_m4(mat); - - if (draw_as == PART_DRAW_PATH) { - geom = DRW_cache_particles_get_hair(psys, NULL); - hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); - DRW_shgroup_call_add(hair_shgrp, geom, mat); - } - } - } - } - } } static void clay_cache_finish(void *vedata) diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index b5806c9f8af..31ce5d4174d 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -113,6 +113,10 @@ static void eevee_cache_populate(void *vedata, Object *ob) } } + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { EEVEE_materials_cache_populate(vedata, sldata, ob); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 868c9ed1ebf..505371d8e3b 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -396,6 +396,7 @@ void DRW_lamp_engine_data_free(struct LampEngineData *led); /* Settings */ bool DRW_object_is_renderable(struct Object *ob); +bool DRW_check_object_visible_within_active_context(struct Object *ob); bool DRW_object_is_flat_normal(const struct Object *ob); int DRW_object_is_mode_shade(const struct Object *ob); @@ -433,6 +434,8 @@ bool DRW_state_show_text(void); bool DRW_state_draw_support(void); bool DRW_state_draw_background(void); +enum eDepsObjectIteratorMode DRW_iterator_mode_get(void); + struct DRWTextStore *DRW_state_text_cache_get(void); /* Avoid too many lookups while drawing */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 80e11c2ac8b..76a92be98d9 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2215,7 +2215,7 @@ bool DRW_object_is_renderable(Object *ob) Scene *scene = DST.draw_ctx.scene; Object *obedit = scene->obedit; - BLI_assert(BKE_object_is_visible(ob)); + BLI_assert(BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE)); if (ob->type == OB_MESH) { if (ob == obedit) { @@ -2234,6 +2234,18 @@ bool DRW_object_is_renderable(Object *ob) return true; } +/** + * Return whether this object is visible depending if + * we are rendering or drawing in the viewport. + */ +bool DRW_check_object_visible_within_active_context(Object *ob) +{ + const eObjectVisibilityCheck mode = DRW_state_is_scene_render() ? + OB_VISIBILITY_CHECK_FOR_RENDER : + OB_VISIBILITY_CHECK_FOR_VIEWPORT; + return BKE_object_is_visible(ob, mode); +} + bool DRW_object_is_flat_normal(const Object *ob) { if (ob->type == OB_MESH) { @@ -2245,7 +2257,6 @@ bool DRW_object_is_flat_normal(const Object *ob) return true; } - /** * Return true if the object has its own draw mode. * Caller must check this is active */ @@ -3403,7 +3414,7 @@ void DRW_draw_render_loop_ex( PROFILE_START(stime); drw_engines_cache_init(); - DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob) + DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob, DRW_iterator_mode_get()) { drw_engines_cache_populate(ob); } @@ -3620,7 +3631,7 @@ void DRW_draw_select_loop( drw_engines_cache_populate(scene->obedit); } else { - DEG_OBJECT_ITER(graph, ob, + DEG_OBJECT_ITER(graph, ob, DRW_iterator_mode_get(), DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI) @@ -3715,7 +3726,7 @@ void DRW_draw_depth_loop( if (cache_is_dirty) { drw_engines_cache_init(); - DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob) + DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob, DRW_iterator_mode_get()) { drw_engines_cache_populate(ob); } @@ -3801,6 +3812,15 @@ bool DRW_state_is_scene_render(void) } /** + * Gives you the iterator mode to use for depsgraph. + */ +eDepsObjectIteratorMode DRW_iterator_mode_get(void) +{ + return DRW_state_is_scene_render() ? DEG_ITER_OBJECT_MODE_RENDER : + DEG_ITER_OBJECT_MODE_VIEWPORT; +} + +/** * Should text draw in this mode? */ bool DRW_state_show_text(void) diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 3d84611f94d..e3800d87a53 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -1648,7 +1648,7 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob) { - if (ob->parent && BKE_object_is_visible(ob->parent)) { + if (ob->parent && DRW_check_object_visible_within_active_context(ob->parent)) { DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]); DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]); } @@ -1763,6 +1763,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) View3D *v3d = draw_ctx->v3d; int theme_id = TH_UNDEFINED; + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob->type == OB_MESH) { + OBJECT_cache_populate_particles(ob, psl); + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + //CollectionEngineSettings *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, ""); //bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire"); @@ -1800,8 +1809,6 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) } } } - - OBJECT_cache_populate_particles(ob, psl); break; } case OB_SURF: diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index c1e45f8280f..50d3593aef6 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -9217,7 +9217,10 @@ afterdraw: /* help lines and so */ if (ob != scene->obedit && ob->parent) { - if (BKE_object_is_visible(ob->parent)) { + const eObjectVisibilityCheck mode = eval_ctx->mode != DAG_EVAL_VIEWPORT ? + OB_VISIBILITY_CHECK_FOR_RENDER : + OB_VISIBILITY_CHECK_FOR_VIEWPORT; + if (BKE_object_is_visible(ob->parent, mode)) { setlinestyle(3); immBegin(GWN_PRIM_LINES, 2); immVertex3fv(pos, ob->obmat[3]); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 79cf5040d9e..dae0a057450 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -208,7 +208,7 @@ typedef struct Object { /* did last modifier stack generation need mapping support? */ char lastNeedMapping; /* bool */ - char pad; + char duplicator_visibility_flag; /* dupli-frame settings */ int dupon, dupoff, dupsta, dupend; @@ -708,6 +708,12 @@ enum { OB_LOCK_ROT4D = 1 << 10, }; +/* ob->duplicator_visibility_flag */ +enum { + OB_DUPLI_FLAG_VIEWPORT = 1 << 0, + OB_DUPLI_FLAG_RENDER = 1 << 1, +}; + /* ob->mode */ typedef enum eObjectMode { OB_MODE_OBJECT = 0, diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index 20ce54a4a01..706fb23ab56 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -168,6 +168,7 @@ static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, Pointe data->flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; + data->mode = DEG_ITER_OBJECT_MODE_RENDER; ((BLI_Iterator *)iter->internal.custom)->valid = true; DEG_iterator_objects_begin(iter->internal.custom, data); @@ -208,6 +209,7 @@ static void rna_Depsgraph_duplis_begin(CollectionPropertyIterator *iter, Pointer DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI; + data->mode = DEG_ITER_OBJECT_MODE_RENDER; ((BLI_Iterator *)iter->internal.custom)->valid = true; DEG_iterator_objects_begin(iter->internal.custom, data); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 00b08957fdd..f64cfef45df 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -870,7 +870,7 @@ static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, Po static void rna_ViewLayer_update_tagged(ViewLayer *UNUSED(view_layer), bContext *C) { Depsgraph *graph = CTX_data_depsgraph(C); - DEG_OBJECT_ITER(graph, ob, + DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_MODE_VIEWPORT, DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY | diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 786598b0731..b83b793b431 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -232,7 +232,13 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA static int rna_Object_is_visible_get(PointerRNA *ptr) { Object *ob = ptr->id.data; - return BKE_object_is_visible(ob); + /* The duplicators final visibility is not evaluated by depsgraph, so it's + * in ob->base_flag & VISIBLED. Instead we need to take into account whether + * we are rendering or not, and the ob->duplicator_visibility_flag. + * However for this assessor we don't know if we are rendering, so we just + * ignore the duplicator visibility + */ + return BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE); } static void rna_Object_collection_properties_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) @@ -2798,6 +2804,14 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + prop = RNA_def_property(srna, "show_duplicator_for_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER); + RNA_def_property_ui_text(prop, "Render Duplicator", "Make duplicator visible when rendering"); + + prop = RNA_def_property(srna, "show_duplicator_for_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); + RNA_def_property_ui_text(prop, "Show Duplicator", "Make duplicator visible in the viewport"); + prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Object_is_visible_get", NULL); RNA_def_property_ui_text(prop, "Visible", "Visible to camera rays, set only on objects evaluated by depsgraph"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 67eaa22fbe4..12e56b8e926 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -2292,11 +2292,6 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Size", "Show particle size"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); - prop = RNA_def_property(srna, "use_render_emitter", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_EMITTER); - RNA_def_property_ui_text(prop, "Emitter", "Render emitter Object also"); - RNA_def_property_update(prop, 0, "rna_Particle_redo"); - prop = RNA_def_property(srna, "show_health", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH); RNA_def_property_ui_text(prop, "Health", "Draw boid health"); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 74de3fcded6..fc60c70c2c4 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4668,9 +4668,8 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * /* the emitter has to be processed first (render levels of modifiers) */ /* so here we only check if the emitter should be rendered */ if (ob->particlesystem.first) { - show_emitter= 0; + show_emitter = (ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0; for (psys=ob->particlesystem.first; psys; psys=psys->next) { - show_emitter += psys->part->draw & PART_DRAW_EMITTER; if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) { psys_has_renderdata |= (psys->renderdata != NULL); psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); |