Draw Manager: basic text overlay support

This commit is contained in:
2017-04-28 04:33:58 +10:00
parent e4d856e31b
commit a680bcd13b
10 changed files with 400 additions and 6 deletions

View File

@@ -61,6 +61,7 @@ set(SRC
intern/draw_cache_impl_mesh.c
intern/draw_common.c
intern/draw_manager.c
intern/draw_manager_text.c
intern/draw_view.c
modes/edit_armature_mode.c
modes/edit_curve_mode.c
@@ -87,6 +88,7 @@ set(SRC
intern/draw_cache.h
intern/draw_cache_impl.h
intern/draw_common.h
intern/draw_manager_text.h
intern/draw_view.h
modes/draw_mode_engines.h
engines/basic/basic_engine.h

View File

@@ -38,6 +38,7 @@ struct bContext;
struct Object;
struct SceneLayer;
struct ViewContext;
struct ViewportEngineData;
struct View3D;
struct rcti;

View File

@@ -62,6 +62,7 @@ struct Object;
struct Batch;
struct DefaultFramebufferList;
struct DefaultTextureList;
struct DRWTextStore;
struct LampEngineData;
struct RenderEngineType;
struct ViewportEngineData;
@@ -310,6 +311,8 @@ bool DRW_is_object_renderable(struct Object *ob);
/* Draw commands */
void DRW_draw_pass(DRWPass *pass);
void DRW_draw_text_cache_queue(struct DRWTextStore *dt);
void DRW_draw_callbacks_pre_scene(void);
void DRW_draw_callbacks_post_scene(void);
@@ -322,6 +325,10 @@ void DRW_select_load_id(unsigned int id);
void DRW_state_dfdy_factors_get(float dfdyfac[2]);
bool DRW_state_is_fbo(void);
bool DRW_state_is_select(void);
bool DRW_state_is_depth(void);
bool DRW_state_show_text(void);
struct DRWTextStore *DRW_state_text_cache_get(void);
/* Avoid too many lookups while drawing */
typedef struct DRWContextState {

View File

@@ -60,6 +60,7 @@
#include "UI_resources.h"
#include "draw_common.h"
#include "draw_manager_text.h"
#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
@@ -485,6 +486,8 @@ static void draw_armature_edit(Object *ob)
update_color(NULL);
const bool show_text = DRW_state_show_text();
for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
@@ -508,6 +511,21 @@ static void draw_armature_edit(Object *ob)
draw_bone_octahedral(eBone, NULL, arm, select_id);
}
/* Draw names of bone */
if (show_text && (arm->flag & ARM_DRAWNAMES)) {
unsigned char color[4];
UI_GetThemeColor4ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
float vec[3];
mid_v3_v3v3(vec, eBone->head, eBone->tail);
mul_m4_v3(ob->obmat, vec);
struct DRWTextStore *dt = DRW_text_cache_ensure();
DRW_text_cache_add(
dt, vec, eBone->name, strlen(eBone->name),
10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
}
/* Draw additional axes */
if (arm->flag & ARM_DRAWAXES) {
draw_axes(eBone, NULL);
@@ -543,7 +561,8 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
}
}
bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
const bool show_text = DRW_state_show_text();
/* being set below */
arm->layer_used = 0;
@@ -578,9 +597,25 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
draw_bone_octahedral(NULL, pchan, arm, select_id);
}
/* Draw names of bone */
if (show_text && (arm->flag & ARM_DRAWNAMES)) {
unsigned char color[4];
UI_GetThemeColor4ubv((arm->flag & ARM_POSEMODE) &&
(pchan->bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
float vec[3];
mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
mul_m4_v3(ob->obmat, vec);
struct DRWTextStore *dt = DRW_text_cache_ensure();
DRW_text_cache_add(
dt, vec, pchan->name, strlen(pchan->name),
10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
}
/* Draw additional axes */
if (arm->flag & ARM_DRAWAXES)
if (arm->flag & ARM_DRAWAXES) {
draw_axes(NULL, pchan);
}
if (is_pose_select) {
index += 0x10000;

View File

@@ -64,6 +64,8 @@
#include "UI_resources.h"
#include "draw_manager_text.h"
/* only for callbacks */
#include "draw_cache_impl.h"
@@ -227,9 +229,17 @@ static struct DRWGlobalState {
float screenvecs[2][3];
float pixsize;
struct {
unsigned int is_select : 1;
unsigned int is_depth : 1;
} options;
/* Current rendering context */
DRWContextState draw_ctx;
/* Convenience pointer to text_store owned by the viewport */
struct DRWTextStore **text_store_p;
ListBase enabled_engines; /* RenderEngineType */
} DST = {NULL};
@@ -1351,6 +1361,16 @@ void DRW_state_reset(void) {}
/** \} */
struct DRWTextStore *DRW_text_cache_ensure(void)
{
BLI_assert(DST.text_store_p);
if (*DST.text_store_p == NULL) {
*DST.text_store_p = DRW_text_cache_create();
}
return *DST.text_store_p;
}
/* -------------------------------------------------------------------- */
/** \name Settings
@@ -1699,6 +1719,15 @@ static void DRW_engines_cache_init(void)
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
data->text_draw_cache = NULL;
}
if (DST.text_store_p == NULL) {
DST.text_store_p = &data->text_draw_cache;
}
double stime = PIL_check_seconds_timer();
data->cache_time = 0.0;
@@ -1776,6 +1805,22 @@ static void DRW_engines_draw_scene(void)
}
}
static void DRW_engines_draw_text(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
double stime = PIL_check_seconds_timer();
if (data->text_draw_cache) {
DRW_text_cache_draw(data->text_draw_cache, DST.draw_ctx.v3d, DST.draw_ctx.ar, false);
}
double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
data->render_time = data->render_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
}
}
static void use_drw_engine(DrawEngineType *engine)
{
LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
@@ -2081,6 +2126,8 @@ void DRW_draw_view(const bContext *C)
DRW_draw_callbacks_post_scene();
ED_region_draw_cb_draw(C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
DRW_engines_draw_text();
/* needed so manipulator isn't obscured */
glClear(GL_DEPTH_BUFFER_BIT);
@@ -2139,6 +2186,8 @@ void DRW_draw_select_loop(
DST.viewport = viewport;
v3d->zbuf = true;
DST.options.is_select = true;
/* Get list of enabled engines */
if (use_obedit) {
DRW_engines_enable_from_mode(obedit_mode);
@@ -2228,6 +2277,8 @@ void DRW_draw_depth_loop(
DST.viewport = viewport;
v3d->zbuf = true;
DST.options.is_depth = true;
/* Get list of enabled engines */
{
DRW_engines_enable_basic();
@@ -2312,7 +2363,21 @@ bool DRW_state_is_fbo(void)
*/
bool DRW_state_is_select(void)
{
return (G.f & G_PICKSEL) != 0;
return DST.options.is_select;
}
bool DRW_state_is_depth(void)
{
return DST.options.is_depth;
}
/**
* Should text draw in this mode?
*/
bool DRW_state_show_text(void)
{
return (DST.options.is_select) == 0 &&
(DST.options.is_depth) == 0;
}
/** \} */

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/** \file blender/draw/intern/draw_manager_text.c
* \ingroup draw
*/
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_math.h"
#include "BIF_gl.h"
#include "GPU_matrix.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_resources.h"
#include "UI_interface.h"
#include "WM_api.h"
#include "BLF_api.h"
#include "draw_manager_text.h"
typedef struct ViewCachedString {
struct ViewCachedString *next, *prev;
float vec[3];
union {
unsigned char ub[4];
int pack;
} col;
short sco[2];
short xoffs;
short flag;
int str_len;
/* str is allocated past the end */
char str[0];
} ViewCachedString;
typedef struct DRWTextStore {
ListBase list;
} DRWTextStore;
DRWTextStore *DRW_text_cache_create(void)
{
DRWTextStore *dt = MEM_callocN(sizeof(*dt), __func__);
return dt;
}
void DRW_text_cache_destroy(struct DRWTextStore *dt)
{
BLI_freelistN(&dt->list);
MEM_freeN(dt);
}
void DRW_text_cache_add(
DRWTextStore *dt,
const float co[3],
const char *str, const int str_len,
short xoffs, short flag,
const unsigned char col[4])
{
int alloc_len;
ViewCachedString *vos;
if (flag & DRW_TEXT_CACHE_STRING_PTR) {
BLI_assert(str_len == strlen(str));
alloc_len = sizeof(void *);
}
else {
alloc_len = str_len + 1;
}
vos = MEM_mallocN(sizeof(ViewCachedString) + alloc_len, __func__);
BLI_addtail(&dt->list, vos);
copy_v3_v3(vos->vec, co);
copy_v4_v4_uchar(vos->col.ub, col);
vos->xoffs = xoffs;
vos->flag = flag;
vos->str_len = str_len;
/* allocate past the end */
if (flag & DRW_TEXT_CACHE_STRING_PTR) {
memcpy(vos->str, &str, alloc_len);
}
else {
memcpy(vos->str, str, alloc_len);
}
}
void DRW_text_cache_draw(
DRWTextStore *dt,
View3D *v3d, ARegion *ar, bool depth_write)
{
RegionView3D *rv3d = ar->regiondata;
ViewCachedString *vos;
int tot = 0;
/* project first and test */
for (vos = dt->list.first; vos; vos = vos->next) {
if (ED_view3d_project_short_ex(
ar,
(vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
vos->vec, vos->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
tot++;
}
else {
vos->sco[0] = IS_CLIPPED;
}
}
if (tot) {
int col_pack_prev = 0;
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
}
float original_proj[4][4];
gpuGetProjectionMatrix(original_proj);
wmOrtho2_region_pixelspace(ar);
gpuPushMatrix();
gpuLoadIdentity();
if (depth_write) {
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
}
else {
glDepthMask(GL_FALSE);
}
const int font_id = BLF_default();
const uiStyle *style = UI_style_get();
BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi);
for (vos = dt->list.first; vos; vos = vos->next) {
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
BLF_color4ubv(font_id, vos->col.ub);
col_pack_prev = vos->col.pack;
}
BLF_position(
font_id,
(float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1]), (depth_write) ? 0.0f : 2.0f);
((vos->flag & DRW_TEXT_CACHE_ASCII) ?
BLF_draw_ascii :
BLF_draw
)(font_id,
(vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str,
vos->str_len);
}
}
if (depth_write) {
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
else {
glDepthMask(GL_TRUE);
}
gpuPopMatrix();
gpuLoadProjectionMatrix(original_proj);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_enable();
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/** \file blender/draw/intern/draw_manager_text.h
* \ingroup draw
*/
#ifndef __DRAW_MANAGER_TEXT_H__
#define __DRAW_MANAGER_TEXT_H__
struct DRWTextStore;
struct DRWTextStore *DRW_text_cache_create(void);
void DRW_text_cache_destroy(struct DRWTextStore *dt);
void DRW_text_cache_add(
struct DRWTextStore *dt,
const float co[3],
const char *str, const int str_len,
short xoffs, short flag,
const unsigned char col[4]);
void DRW_text_cache_draw(
struct DRWTextStore *dt,
struct View3D *v3d, struct ARegion *ar, bool depth_write);
enum {
DRW_TEXT_CACHE_ASCII = (1 << 0),
DRW_TEXT_CACHE_GLOBALSPACE = (1 << 1),
DRW_TEXT_CACHE_LOCALCLIP = (1 << 2),
/* reference the string by pointer */
DRW_TEXT_CACHE_STRING_PTR = (1 << 3),
};
/* draw_manager.c */
struct DRWTextStore *DRW_text_cache_ensure(void);
#endif /* __DRAW_MANAGER_TEXT_H__ */

View File

@@ -47,6 +47,7 @@
#include "UI_resources.h"
#include "draw_mode_engines.h"
#include "draw_manager_text.h"
#include "draw_common.h"
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
@@ -1179,6 +1180,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
SceneLayer *sl = draw_ctx->sl;
int theme_id = TH_UNDEFINED;
//CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
@@ -1190,7 +1192,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (ob != obedit) {
struct Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or(stl, theme_id, NULL);
if (shgroup != NULL) {
DRW_shgroup_call_add(shgroup, geom, ob->obmat);
@@ -1208,7 +1210,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
Object *obedit = scene->obedit;
if (ob != obedit) {
struct Batch *geom = DRW_cache_lattice_wire_get(ob);
int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
}
DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
DRW_shgroup_call_add(shgroup, geom, ob->obmat);
@@ -1221,7 +1225,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
Object *obedit = scene->obedit;
if (ob != obedit) {
struct Batch *geom = DRW_cache_curve_edge_wire_get(ob);
int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
}
DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
DRW_shgroup_call_add(shgroup, geom, ob->obmat);
}
@@ -1266,6 +1272,21 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
DRW_shgroup_object_center(stl, ob);
DRW_shgroup_relationship_lines(stl, ob);
if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) {
struct DRWTextStore *dt = DRW_text_cache_ensure();
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
}
unsigned char color[4];
UI_GetThemeColor4ubv(theme_id, color);
DRW_text_cache_add(
dt, ob->obmat[3],
ob->id.name + 2, strlen(ob->id.name + 2),
10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
}
}
static void OBJECT_draw_scene(void *vedata)

View File

@@ -66,6 +66,9 @@ typedef struct ViewportEngineData {
PassList *psl;
StorageList *stl;
/* we may want to put this elsewhere */
struct DRWTextStore *text_draw_cache;
/* Profiling data */
double init_time;
double cache_time;

View File

@@ -123,6 +123,13 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport)
MEM_freeN(data->psl);
MEM_freeN(data->stl);
/* We could handle this in the DRW module */
if (data->text_draw_cache) {
extern void DRW_text_cache_destroy(struct DRWTextStore *dt);
DRW_text_cache_destroy(data->text_draw_cache);
data->text_draw_cache = NULL;
}
MEM_freeN(data);
BLI_remlink(&viewport->data, link);