T54983: Bone selection overlay

Bone selection overlay is only available in pose mode.
and when active overrules the selection buffer.

This is currently `tricked` by switching the draw engines, but this is
an exception. Not sure how to solve this in a better way.

After this is solved we can look at how to localize the dim effect to only the objects connected to the active armatures. Currently it dims the whole screen (including background).

@campbellbarton I added you as reviewer as it you have done a lot in the DRW_draw_select_loop

Reviewers: campbellbarton, fclem

Reviewed By: fclem

Subscribers: campbellbarton

Tags: #bf_blender_2.8, #code_quest

Maniphest Tasks: T54983

Differential Revision: https://developer.blender.org/D3241
This commit is contained in:
Jeroen Bakker 2018-05-11 08:16:41 +02:00
parent 266638d783
commit 6d155dc462
Notes: blender-bot 2023-02-13 15:19:58 +01:00
Referenced by issue #98456, Eydropper selection of custom bone shape do not work for 3D view with Xray
11 changed files with 162 additions and 6 deletions

View File

@ -3656,6 +3656,7 @@ class VIEW3D_PT_overlay(Panel):
col = layout.column()
col.active = display_all
col.prop(overlay, "transparent_bones")
col.prop(overlay, "show_bone_selection")
elif context.mode == 'EDIT_ARMATURE':
col.separator()

View File

@ -423,6 +423,7 @@ bool modifiers_isClothEnabled(struct Object *ob);
bool modifiers_isParticleEnabled(struct Object *ob);
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
struct Object *modifiers_isDeformedByCurve(struct Object *ob);
bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm);

View File

@ -627,6 +627,27 @@ Object *modifiers_isDeformedByArmature(Object *ob)
return NULL;
}
Object *modifiers_isDeformedByMeshDeform(Object *ob)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
MeshDeformModifierData *mdmd = NULL;
/* return the first selected armature, this lets us use multiple armatures */
for (; md; md = md->next) {
if (md->type == eModifierType_MeshDeform) {
mdmd = (MeshDeformModifierData *) md;
if (mdmd->object && (mdmd->object->flag & SELECT))
return mdmd->object;
}
}
if (mdmd) /* if were still here then return the last armature */
return mdmd->object;
return NULL;
}
/* Takes an object and returns its first selected lattice, else just its lattice
* This should work for multiple lattices per object
*/

View File

@ -1570,6 +1570,15 @@ void DRW_draw_select_loop(
obedit_mode = CTX_MODE_EDIT_ARMATURE;
}
}
bool use_bone_selection_overlay = false;
if (v3d->overlay.flag &= V3D_OVERLAY_BONE_SELECTION) {
if (!(v3d->flag2 &= V3D_RENDER_OVERRIDE)) {
Object *obpose = OBPOSE_FROM_OBACT(obact);
if (obpose) {
use_bone_selection_overlay = true;
}
}
}
struct GPUViewport *viewport = GPU_viewport_create();
GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)});
@ -1584,8 +1593,17 @@ void DRW_draw_select_loop(
drw_engines_enable_from_mode(obedit_mode);
}
else {
drw_engines_enable_basic();
drw_engines_enable_from_object_mode();
/* when in pose mode and overlays enable and bone selection overlay
active, switch order as the bone selection must have more precedence
than the rest of the scene */
if (use_bone_selection_overlay) {
drw_engines_enable_from_object_mode();
drw_engines_enable_basic();
}
else {
drw_engines_enable_basic();
drw_engines_enable_from_object_mode();
}
}
/* Setup viewport */

View File

@ -22,10 +22,13 @@
/** \file blender/draw/modes/pose_mode.c
* \ingroup draw
*/
#include "BKE_modifier.h"
#include "DNA_modifier_types.h"
#include "DNA_view3d_types.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "DNA_view3d_types.h"
/* If builtin shaders are needed */
#include "GPU_shader.h"
@ -50,6 +53,7 @@ typedef struct POSE_PassList {
struct DRWPass *bone_envelope;
struct DRWPass *bone_axes;
struct DRWPass *relationship;
struct DRWPass *bone_selection;
} POSE_PassList;
typedef struct POSE_StorageList {
@ -67,10 +71,33 @@ typedef struct POSE_Data {
/* *********** STATIC *********** */
typedef struct POSE_PrivateData {
char pad; /* UNUSED */
DRWShadingGroup *bone_selection_shgrp;
} POSE_PrivateData; /* Transient data */
static struct {
struct GPUShader *bone_selection_sh;
} e_data = {NULL};
static float blend_color[4] = {0.0, 0.0, 0.0, 0.5};
/* *********** FUNCTIONS *********** */
static bool POSE_is_bone_selection_overlay_active(void)
{
const DRWContextState *dcs = DRW_context_state_get();
const View3D *v3d = dcs->v3d;
return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECTION);
}
static void POSE_engine_init(void *UNUSED(vedata))
{
if (!e_data.bone_selection_sh) {
e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
}
}
static void POSE_engine_free(void)
{
}
/* Here init all passes and shading groups
* Assume that all Passes are NULL */
@ -120,12 +147,42 @@ static void POSE_cache_init(void *vedata)
DRW_STATE_BLEND | DRW_STATE_WIRE;
psl->relationship = DRW_pass_create("Bone Relationship Pass", state);
}
{
if (POSE_is_bone_selection_overlay_active()) {
DRWShadingGroup *grp;
psl->bone_selection = DRW_pass_create("Bone Selection", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND);
grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection);
DRW_shgroup_uniform_vec4(grp, "color", blend_color, 1);
stl->g_data->bone_selection_shgrp = grp;
}
}
}
static bool POSE_is_driven_by_active_armature(Object *ob)
{
Object *armature = modifiers_isDeformedByArmature(ob);
if (armature) {
const DRWContextState *draw_ctx = DRW_context_state_get();
bool is_active = DRW_pose_mode_armature(armature, draw_ctx->obact);
if (!is_active && armature->proxy_from) {
is_active = DRW_pose_mode_armature(armature->proxy_from, draw_ctx->obact);
}
return is_active;
} else {
Object *meshDeform = modifiers_isDeformedByMeshDeform(ob);
if (meshDeform) {
return POSE_is_driven_by_active_armature(meshDeform);
}
}
return false;
}
/* Add geometry to shading groups. Execute for each objects */
static void POSE_cache_populate(void *vedata, Object *ob)
{
POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
/* In the future this will allow us to implement face manipulators,
@ -143,6 +200,11 @@ static void POSE_cache_populate(void *vedata, Object *ob)
};
DRW_shgroup_armature_pose(ob, passes);
}
} else if (ob->type == OB_MESH && POSE_is_bone_selection_overlay_active() && POSE_is_driven_by_active_armature(ob)) {
struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
DRW_shgroup_call_object_add(stl->g_data->bone_selection_shgrp, geom, ob);
}
}
}
@ -178,6 +240,14 @@ static void POSE_draw_scene(void *vedata)
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active();
if(bone_selection_overlay) {
GPU_framebuffer_bind(dfbl->default_fb);
DRW_draw_pass(psl->bone_selection);
GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0);
GPU_framebuffer_bind(dfbl->default_fb);
}
DRW_draw_pass(psl->bone_envelope);
@ -228,8 +298,8 @@ DrawEngineType draw_engine_pose_type = {
NULL, NULL,
N_("PoseMode"),
&POSE_data_size,
NULL,
NULL,
&POSE_engine_init,
&POSE_engine_free,
&POSE_cache_init,
&POSE_cache_populate,
NULL,

View File

@ -137,6 +137,7 @@ void POSE_OT_rotation_mode_set(struct wmOperatorType *ot);
void POSE_OT_quaternions_flip(struct wmOperatorType *ot);
void POSE_OT_bone_layers(struct wmOperatorType *ot);
void POSE_OT_toggle_bone_selection_overlay(struct wmOperatorType *ot);
/* ******************************************************* */
/* Pose Tool Utilities (for PoseLib, Pose Sliding, etc.) */

View File

@ -131,6 +131,8 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_quaternions_flip);
WM_operatortype_append(POSE_OT_bone_layers);
WM_operatortype_append(POSE_OT_toggle_bone_selection_overlay);
WM_operatortype_append(POSE_OT_propagate);
@ -363,6 +365,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_layers_show_all", ACCENTGRAVEKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_armature_layers", MKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_bone_layers", MKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "POSE_OT_toggle_bone_selection_overlay", ZKEY, KM_PRESS, 0, 0);
/* special transforms: */
/* 1) envelope/b-bone size */

View File

@ -63,6 +63,7 @@
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_view3d.h"
#include "UI_interface.h"
@ -1240,3 +1241,34 @@ void POSE_OT_quaternions_flip(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* -------------------------------------------------------------------- */
/** \name Toggle Bone selection Overlay Operator
* \{ */
static int toggle_bone_selection_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECTION;
ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
}
static int pose_select_linked_poll(bContext *C)
{
return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
}
void POSE_OT_toggle_bone_selection_overlay(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Bone Selection Overlay";
ot->description = "Toggle bone selection overlay of the viewport";
ot->idname = "POSE_OT_toggle_bone_selection_overlay";
/* api callbacks */
ot->exec = toggle_bone_selection_exec;
ot->poll = pose_select_linked_poll;
}
/** \} */

View File

@ -1678,6 +1678,8 @@ extern const char *RE_engine_id_CYCLES;
(((workspace)->object_mode & OD_MODE_EDIT) ? OBACT(_view_layer) : NULL)
#define OBEDIT_FROM_OBACT(ob) \
((ob) ? (((ob)->mode & OB_MODE_EDIT) ? ob : NULL) : NULL)
#define OBPOSE_FROM_OBACT(ob) \
((ob) ? (((ob)->mode & OB_MODE_POSE) ? ob : NULL) : NULL)
#define OBEDIT_FROM_VIEW_LAYER(view_layer) \
OBEDIT_FROM_OBACT(OBACT(view_layer))

View File

@ -346,6 +346,7 @@ enum {
enum {
V3D_OVERLAY_FACE_ORIENTATION = (1 << 0),
V3D_OVERLAY_HIDE_CURSOR = (1 << 1),
V3D_OVERLAY_BONE_SELECTION = (1 << 2),
};
/* View3DOverlay->edit_flag */

View File

@ -2323,6 +2323,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Face Orientation", "Show the Face Orientation Overlay");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_bone_selection", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_BONE_SELECTION);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Bone Selection", "Show the Bone Selection Overlay");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_paint_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.paint_flag", V3D_OVERLAY_PAINT_WIRE);
RNA_def_property_ui_text(prop, "Show Wire", "Use wireframe display in painting modes");