Wireframe: Add object and random coloring option in wireframe mode

The option is separated from the solid mode color option.

Random color uses the same method as solid mode.

Selection state is indicated by a brighter color that is outside the
brightness range of the unselected state colors. The active state is
indicated by the outlines that is, now, still drawn in wireframe mode.

Coloring of the selection / active outline is not optimal because it
can look ugly in some cases of color combination. But the outline color
is using index range coloring so it's not trivial to change the color of
the outline per object. For now we use the same outline color used in solid
mode for consistency and also still add an emphasis on the selected objects.

The Single color option uses the theme color. Maybe it would be nice to
change the name of it in a latter commit to avoid confusion.
This commit is contained in:
Clément Foucault 2019-02-22 16:06:13 +01:00
parent e278b38b92
commit 7372058649
6 changed files with 148 additions and 49 deletions

View File

@ -4583,7 +4583,9 @@ class VIEW3D_PT_shading_color(Panel):
def draw(self, context):
shading = VIEW3D_PT_shading.get_shading(context)
if shading.type != 'WIREFRAME':
if shading.type == 'WIREFRAME':
self.layout.row().prop(shading, "wireframe_color_type", expand=True)
else:
self._draw_color_type(context)
self.layout.separator()
self._draw_background_color(context)

View File

@ -2807,5 +2807,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Versioning code until next subversion bump goes here. */
/* Add wireframe color. */
if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "wire_color_type")) {
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
v3d->shading.wire_color_type = V3D_SHADING_SINGLE_COLOR;
}
}
}
}
}
}
}

View File

@ -307,6 +307,7 @@ typedef struct OBJECT_PrivateData {
int id_ofs_prb_transform;
bool xray_enabled;
bool xray_enabled_and_not_wire;
} OBJECT_PrivateData; /* Transient data */
static struct {
@ -995,7 +996,9 @@ static void OBJECT_cache_init(void *vedata)
}
g_data = stl->g_data;
g_data->xray_enabled = XRAY_ENABLED(draw_ctx->v3d) && (draw_ctx->v3d->shading.type < OB_MATERIAL);
g_data->xray_enabled = XRAY_ENABLED(draw_ctx->v3d) &&
(draw_ctx->v3d->shading.type < OB_MATERIAL);
g_data->xray_enabled_and_not_wire = g_data->xray_enabled && draw_ctx->v3d->shading.type > OB_WIRE;
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE;
@ -1003,7 +1006,7 @@ static void OBJECT_cache_init(void *vedata)
GPUShader *sh = sh_data->outline_prepass;
if (g_data->xray_enabled) {
if (g_data->xray_enabled_and_not_wire) {
sh = sh_data->outline_prepass_wire;
}
@ -1050,7 +1053,7 @@ static void OBJECT_cache_init(void *vedata)
psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state);
GPUShader *sh = (g_data->xray_enabled) ? sh_data->outline_detect_wire : sh_data->outline_detect;
GPUShader *sh = (g_data->xray_enabled_and_not_wire) ? sh_data->outline_detect_wire : sh_data->outline_detect;
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->outlines_search);
DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx);
DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx);
@ -2908,7 +2911,6 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
const bool do_outlines = (
(draw_ctx->v3d->flag & V3D_SELECT_OUTLINE) && ((ob->base_flag & BASE_SELECTED) != 0) &&
(draw_ctx->v3d->shading.type != OB_WIRE) &&
((DRW_object_is_renderable(ob) && (ob->dt > OB_WIRE)) || (ob->dt == OB_WIRE)));
const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
const bool hide_object_extra = (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) != 0;
@ -2926,7 +2928,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
DRW_object_is_flat(ob, &flat_axis) &&
DRW_object_axis_orthogonal_to_view(ob, flat_axis));
if (stl->g_data->xray_enabled || is_flat_object_viewed_from_side) {
if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) {
geom = DRW_cache_object_edge_detection_get(ob, NULL);
}
else {

View File

@ -29,6 +29,8 @@
#include "BKE_object.h"
#include "BKE_global.h"
#include "BLI_hash.h"
#include "GPU_shader.h"
#include "DRW_render.h"
@ -39,6 +41,7 @@
#endif
/* Structures */
typedef struct OVERLAY_StorageList {
struct OVERLAY_PrivateData *g_data;
} OVERLAY_StorageList;
@ -59,6 +62,7 @@ typedef struct OVERLAY_Data {
typedef struct OVERLAY_PrivateData {
DRWShadingGroup *face_orientation_shgrp;
DRWShadingGroup *face_wires_shgrp;
BLI_mempool *wire_color_mempool;
View3DOverlay overlay;
float wire_step_param;
bool ghost_stencil_test;
@ -102,7 +106,7 @@ static void overlay_engine_init(void *vedata)
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
stl->g_data->ghost_stencil_test = false;
@ -172,6 +176,13 @@ static void overlay_cache_init(void *vedata)
if (v3d->shading.type == OB_WIRE) {
g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
g_data->show_overlays = true;
if (ELEM(v3d->shading.wire_color_type,
V3D_SHADING_OBJECT_COLOR,
V3D_SHADING_RANDOM_COLOR))
{
g_data->wire_color_mempool = BLI_mempool_create(sizeof(float[3]), 0, 512, 0);
}
}
{
@ -221,6 +232,92 @@ static void overlay_cache_init(void *vedata)
}
}
static void overlay_wire_color_get(
const View3D *v3d, const OVERLAY_PrivateData *pd, const Object *ob, const bool use_coloring,
float **rim_col, float **wire_col)
{
#ifndef NDEBUG
*rim_col = NULL;
*wire_col = NULL;
#endif
const DRWContextState *draw_ctx = DRW_context_state_get();
if (UNLIKELY(ob->base_flag & BASE_FROM_SET)) {
*rim_col = G_draw.block.colorDupli;
*wire_col = G_draw.block.colorDupli;
}
else if (UNLIKELY(ob->base_flag & BASE_FROM_DUPLI)) {
if (ob->base_flag & BASE_SELECTED) {
if (G.moving & G_TRANSFORM_OBJ) {
*rim_col = G_draw.block.colorTransform;
}
else {
*rim_col = G_draw.block.colorDupliSelect;
}
}
else {
*rim_col = G_draw.block.colorDupli;
}
*wire_col = G_draw.block.colorDupli;
}
else if ((ob->base_flag & BASE_SELECTED) && use_coloring) {
if (G.moving & G_TRANSFORM_OBJ) {
*rim_col = G_draw.block.colorTransform;
}
else if (ob == draw_ctx->obact) {
*rim_col = G_draw.block.colorActive;
}
else {
*rim_col = G_draw.block.colorSelect;
}
*wire_col = G_draw.block.colorWire;
}
else {
*rim_col = G_draw.block.colorWire;
*wire_col = G_draw.block.colorWire;
}
if (v3d->shading.type == OB_WIRE) {
if (ELEM(v3d->shading.wire_color_type,
V3D_SHADING_OBJECT_COLOR,
V3D_SHADING_RANDOM_COLOR))
{
*wire_col = BLI_mempool_alloc(pd->wire_color_mempool);
*rim_col = BLI_mempool_alloc(pd->wire_color_mempool);
if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) {
linearrgb_to_srgb_v3_v3(*wire_col, ob->color);
mul_v3_fl(*wire_col, 0.5f);
copy_v3_v3(*rim_col, *wire_col);
}
else {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
if (ob->id.lib) {
hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name);
}
float hue = BLI_hash_int_01(hash);
float hsv[3] = {hue, 0.75f, 0.8f};
hsv_to_rgb_v(hsv, *wire_col);
copy_v3_v3(*rim_col, *wire_col);
}
if ((ob->base_flag & BASE_SELECTED) && use_coloring) {
/* "Normalize" color. */
add_v3_fl(*wire_col, 1e-4f);
float brightness = max_fff((*wire_col)[0], (*wire_col)[1], (*wire_col)[2]);
mul_v3_fl(*wire_col, (0.5f / brightness));
add_v3_fl(*rim_col, 0.75f);
}
else {
mul_v3_fl(*rim_col, 0.5f);
add_v3_fl(*wire_col, 0.5f);
}
}
}
BLI_assert(*rim_col && *wire_col);
}
static void overlay_cache_populate(void *vedata, Object *ob)
{
OVERLAY_Data *data = vedata;
@ -267,49 +364,12 @@ static void overlay_cache_populate(void *vedata, Object *ob)
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES);
const bool is_wire = (ob->dt < OB_SOLID);
const bool use_coloring = (!is_edit_mode && !is_sculpt_mode && !has_edit_mesh_cage);
const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF;
float *rim_col, *wire_col;
DRWShadingGroup *shgrp = NULL;
const float *rim_col = NULL;
const float *wire_col = NULL;
if (UNLIKELY(ob->base_flag & BASE_FROM_SET)) {
rim_col = G_draw.block.colorDupli;
wire_col = G_draw.block.colorDupli;
}
else if (UNLIKELY(ob->base_flag & BASE_FROM_DUPLI)) {
if (ob->base_flag & BASE_SELECTED) {
if (G.moving & G_TRANSFORM_OBJ) {
rim_col = G_draw.block.colorTransform;
}
else {
rim_col = G_draw.block.colorDupliSelect;
}
}
else {
rim_col = G_draw.block.colorDupli;
}
wire_col = G_draw.block.colorDupli;
}
else if ((ob->base_flag & BASE_SELECTED) &&
(!is_edit_mode && !is_sculpt_mode && !has_edit_mesh_cage))
{
if (G.moving & G_TRANSFORM_OBJ) {
rim_col = G_draw.block.colorTransform;
}
else if (ob == draw_ctx->obact) {
rim_col = G_draw.block.colorActive;
}
else {
rim_col = G_draw.block.colorSelect;
}
wire_col = G_draw.block.colorWire;
}
else {
rim_col = G_draw.block.colorWire;
wire_col = G_draw.block.colorWire;
}
BLI_assert(rim_col && wire_col);
overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col);
struct GPUBatch *geom;
geom = DRW_cache_object_face_wireframe_get(ob);
@ -372,6 +432,7 @@ static void overlay_draw_scene(void *vedata)
{
OVERLAY_Data *data = vedata;
OVERLAY_PassList *psl = data->psl;
OVERLAY_StorageList *stl = data->stl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@ -380,7 +441,8 @@ static void overlay_draw_scene(void *vedata)
}
DRW_draw_pass(psl->face_orientation_pass);
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
/* This is replaced by the next code block */
// MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
if (dfbl->multisample_fb != NULL) {
DRW_stats_query_start("Multisample Blit");
@ -399,6 +461,12 @@ static void overlay_draw_scene(void *vedata)
/* TODO(fclem): find a way to unify the multisample pass together
* (non meshes + armature + wireframe) */
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
/* XXX TODO(fclem) do not discard data after drawing! Store them per viewport. */
if (stl->g_data->wire_color_mempool) {
BLI_mempool_destroy(stl->g_data->wire_color_mempool);
stl->g_data->wire_color_mempool = NULL;
}
}
static void overlay_engine_free(void)

View File

@ -154,7 +154,8 @@ typedef struct View3DShading {
char light;
char background_type;
char cavity_type;
char pad[7];
char wire_color_type;
char pad[6];
/** FILE_MAXFILE. */
char studio_light[256];

View File

@ -804,6 +804,11 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_TEXTURE_COLOR);
}
}
else if (shading->type == OB_WIRE) {
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR);
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_OBJECT_COLOR);
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_RANDOM_COLOR);
}
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@ -2536,6 +2541,13 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Color", "Color Type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "wireframe_color_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "wire_color_type");
RNA_def_property_enum_items(prop, rna_enum_shading_color_type_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_View3DShading_color_type_itemf");
RNA_def_property_ui_text(prop, "Color", "Color Type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "single_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "single_color");
RNA_def_property_array(prop, 3);