Implement duplicator viewport/render visibility options
This allows a duplicator (as known as dupli parent) to be in a visible collection so its duplicated objects are visible, however while being invisible for the final render. An object that is a particle emitter is also considered a duplicator. Many thanks for the reviewers for the extense feedback. Reviewers: sergey, campbellbarton Differential Revision: https://developer.blender.org/D2966
This commit is contained in:
parent
103dd66057
commit
b89f2276e5
@ -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();
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 | \
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
@ -3800,6 +3811,15 @@ bool DRW_state_is_scene_render(void)
|
||||
return DST.options.is_scene_render;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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?
|
||||
*/
|
||||
|
@ -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:
|
||||
|
@ -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]);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 |
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user