Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/DRW_engine.h1
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c75
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_manager.c7
-rw-r--r--source/blender/draw/intern/draw_manager.h1
5 files changed, 69 insertions, 16 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 8a35ab2aeb9..a125a13eaf9 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -110,6 +110,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
bool use_obedit_skip,
bool draw_surface,
bool use_nearest,
+ const bool do_material_sub_selection,
const struct rcti *rect,
DRW_SelectPassFn select_pass_fn,
void *select_pass_user_data,
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index c120df7e897..87f5c6f5857 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -25,9 +25,12 @@
#include "DRW_render.h"
+#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BLI_alloca.h"
+
#include "DNA_particle_types.h"
#include "GPU_shader.h"
@@ -80,6 +83,7 @@ typedef struct BASIC_PrivateData {
DRWShadingGroup *depth_shgrp[2];
DRWShadingGroup *depth_shgrp_cull[2];
DRWShadingGroup *depth_hair_shgrp[2];
+ bool use_material_slot_selection;
} BASIC_PrivateData; /* Transient data */
/* Functions */
@@ -131,6 +135,8 @@ static void basic_cache_init(void *vedata)
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
+ stl->g_data->use_material_slot_selection = DRW_state_is_material_select();
+
/* Twice for normal and in front objects. */
for (int i = 0; i < 2; i++) {
DRWState clip_state = (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? DRW_STATE_CLIP_PLANES : 0;
@@ -155,6 +161,38 @@ static void basic_cache_init(void *vedata)
}
}
+/* TODO(fclem): DRW_cache_object_surface_material_get needs a refactor to allow passing NULL
+ * instead of gpumat_array. Avoiding all this boilerplate code. */
+static struct GPUBatch **basic_object_surface_material_get(Object *ob)
+{
+ const int materials_len = DRW_cache_object_material_count_get(ob);
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len);
+
+ return DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
+}
+
+static void basic_cache_populate_particles(void *vedata, Object *ob)
+{
+ const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
+ BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+ for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) {
+ if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
+ continue;
+ }
+ ParticleSettings *part = psys->part;
+ const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+ if (draw_as == PART_DRAW_PATH) {
+ struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
+ if (stl->g_data->use_material_slot_selection) {
+ const short material_slot = part->omat;
+ DRW_select_load_id(ob->runtime.select_id | (material_slot << 16));
+ }
+ DRW_shgroup_call(stl->g_data->depth_hair_shgrp[do_in_front], hairs, NULL);
+ }
+ }
+}
+
static void basic_cache_populate(void *vedata, Object *ob)
{
BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
@@ -165,24 +203,13 @@ static void basic_cache_populate(void *vedata, Object *ob)
return;
}
- bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
-
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob != draw_ctx->object_edit) {
- for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) {
- if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
- continue;
- }
- ParticleSettings *part = psys->part;
- const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
- if (draw_as == PART_DRAW_PATH) {
- struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
- DRW_shgroup_call(stl->g_data->depth_hair_shgrp[do_in_front], hairs, NULL);
- }
- }
+ basic_cache_populate_particles(vedata, ob);
}
/* Make flat object selectable in ortho view if wireframe is enabled. */
+ const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
if ((draw_ctx->v3d->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
(draw_ctx->v3d->shading.type == OB_WIRE) || (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE)) {
int flat_axis = 0;
@@ -211,9 +238,25 @@ static void basic_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_sculpt(shgrp, ob, false, false);
}
else {
- struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
- if (geom) {
- DRW_shgroup_call(shgrp, geom, ob);
+ if (stl->g_data->use_material_slot_selection && BKE_object_supports_material_slots(ob)) {
+ struct GPUBatch **geoms = basic_object_surface_material_get(ob);
+ if (geoms) {
+ const int materials_len = DRW_cache_object_material_count_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ if (geoms[i] == NULL) {
+ continue;
+ }
+ const short material_slot_select_id = i + 1;
+ DRW_select_load_id(ob->runtime.select_id | (material_slot_select_id << 16));
+ DRW_shgroup_call(shgrp, geoms[i], ob);
+ }
+ }
+ }
+ else {
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ DRW_shgroup_call(shgrp, geom, ob);
+ }
}
}
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 6639a100af9..660a4adaf51 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -731,6 +731,7 @@ void DRW_select_load_id(uint id);
/* Draw State */
bool DRW_state_is_fbo(void);
bool DRW_state_is_select(void);
+bool DRW_state_is_material_select(void);
bool DRW_state_is_depth(void);
bool DRW_state_is_image_render(void);
bool DRW_state_is_scene_render(void);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 9590a4aa7ee..aca645acc09 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2232,6 +2232,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
bool use_obedit_skip,
bool draw_surface,
bool UNUSED(use_nearest),
+ const bool do_material_sub_selection,
const rcti *rect,
DRW_SelectPassFn select_pass_fn,
void *select_pass_user_data,
@@ -2299,6 +2300,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DST.viewport = viewport;
DST.options.is_select = true;
+ DST.options.is_material_select = do_material_sub_selection;
drw_task_graph_init();
/* Get list of enabled engines */
if (use_obedit) {
@@ -2776,6 +2778,11 @@ bool DRW_state_is_select(void)
return DST.options.is_select;
}
+bool DRW_state_is_material_select(void)
+{
+ return DST.options.is_material_select;
+}
+
bool DRW_state_is_depth(void)
{
return DST.options.is_depth;
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 1747ca752c7..c09126c98ef 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -553,6 +553,7 @@ typedef struct DRWManager {
struct {
uint is_select : 1;
+ uint is_material_select : 1;
uint is_depth : 1;
uint is_image_render : 1;
uint is_scene_render : 1;