Viewport Text Drawing: replace single allocs with a memarena

- pass label strlen since in many cases its already known.
- use single linked list for cached text drawing.
- add BLI_link_utils.h for single linked list macros.

own tests give approx 22% overall speedup.
This commit is contained in:
Campbell Barton 2014-04-17 15:14:07 +10:00
parent 1b9db9911d
commit 3e3efae7e9
9 changed files with 267 additions and 134 deletions

View File

@ -0,0 +1,46 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BLI_LINK_UTILS_H__
#define __BLI_LINK_UTILS_H__
/** \file BLI_link_utils.h
* \ingroup bli
* \brief Single link-list utility macros. (header only api).
*
* Use this api when the structure defines its own ``next`` pointer
* and a double linked list such as #ListBase isnt needed.
*/
#define BLI_LINKS_PREPEND(list, link) { \
CHECK_TYPE_PAIR(list, link); \
(link)->next = list; \
list = link; \
} (void)0
#define BLI_LINKS_FREE(list) { \
while (list) { \
void *next = list->next; \
MEM_freeN(list); \
list = next; \
} \
} (void)0
#endif /* __BLI_LINK_UTILS_H__ */

View File

@ -210,8 +210,8 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac);
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, const char *str, const char col[4]);
void UI_view2d_text_cache_rectf(struct View2D *v2d, const struct rctf *rect, const char *str, const char col[4]);
void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4]);
void UI_view2d_text_cache_rectf(struct View2D *v2d, const struct rctf *rect, const char *str, size_t str_len, const char col[4]);
void UI_view2d_text_cache_draw(struct ARegion *ar);
/* operators */

View File

@ -38,9 +38,13 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_link_utils.h"
#include "BLI_rect.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_timecode.h"
#include "BKE_context.h"
@ -2175,56 +2179,76 @@ short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y)
/* ******************* view2d text drawing cache ******************** */
/* assumes caches are used correctly, so for time being no local storage in v2d */
static ListBase strings = {NULL, NULL};
typedef struct View2DString {
struct View2DString *next, *prev;
struct View2DString *next;
union {
unsigned char ub[4];
int pack;
} col;
int mval[2];
rcti rect;
int mval[2];
} View2DString;
/* assumes caches are used correctly, so for time being no local storage in v2d */
static MemArena *g_v2d_strings_arena = NULL;
static View2DString *g_v2d_strings = NULL;
void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, const char col[4])
void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4])
{
int mval[2];
BLI_assert(str_len == strlen(str));
UI_view2d_view_to_region(v2d, x, y, mval, mval + 1);
if (mval[0] != V2D_IS_CLIPPED && mval[1] != V2D_IS_CLIPPED) {
int len = strlen(str) + 1;
/* use calloc, rect has to be zeroe'd */
View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString");
char *v2s_str = (char *)(v2s + 1);
memcpy(v2s_str, str, len);
int alloc_len = str_len + 1;
View2DString *v2s;
if (g_v2d_strings_arena == NULL) {
g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
}
v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
BLI_addtail(&strings, v2s);
v2s->col.pack = *((int *)col);
memset(&v2s->rect, 0, sizeof(v2s->rect));
v2s->mval[0] = mval[0];
v2s->mval[1] = mval[1];
memcpy(v2s + 1, str, alloc_len);
}
}
/* no clip (yet) */
void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, const char col[4])
void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, size_t str_len, const char col[4])
{
int len = strlen(str) + 1;
View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString");
char *v2s_str = (char *)(v2s + 1);
memcpy(v2s_str, str, len);
int alloc_len = str_len;
View2DString *v2s;
BLI_assert(str_len == strlen(str));
if (g_v2d_strings_arena == NULL) {
g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
}
v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len);
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
v2s->col.pack = *((int *)col);
UI_view2d_to_region_no_clip(v2d, rect->xmin, rect->ymin, &v2s->rect.xmin, &v2s->rect.ymin);
UI_view2d_to_region_no_clip(v2d, rect->xmax, rect->ymax, &v2s->rect.xmax, &v2s->rect.ymax);
v2s->col.pack = *((int *)col);
v2s->mval[0] = v2s->rect.xmin;
v2s->mval[1] = v2s->rect.ymin;
BLI_addtail(&strings, v2s);
memcpy(v2s + 1, str, alloc_len);
}
@ -2234,7 +2258,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
int col_pack_prev = 0;
/* investigate using BLF_ascender() */
const float default_height = strings.first ? BLF_height_default("28", 3) : 0.0f;
const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f;
// glMatrixMode(GL_PROJECTION);
// glPushMatrix();
@ -2242,7 +2266,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
// glPushMatrix();
ED_region_pixelspace(ar);
for (v2s = strings.first; v2s; v2s = v2s->next) {
for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
const char *str = (const char *)(v2s + 1);
int xofs = 0, yofs;
@ -2263,14 +2287,17 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLF_disable_default(BLF_CLIPPING);
}
}
g_v2d_strings = NULL;
if (g_v2d_strings_arena) {
BLI_memarena_free(g_v2d_strings_arena);
g_v2d_strings_arena = NULL;
}
// glMatrixMode(GL_PROJECTION);
// glPopMatrix();
// glMatrixMode(GL_MODELVIEW);
// glPopMatrix();
if (strings.first)
BLI_freelistN(&strings);
}

View File

@ -428,16 +428,17 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i
{
short notSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
char str[256];
size_t str_len;
char col[4];
float xofs;
rctf rect;
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index);
str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index);
}
else {
BLI_strncpy(str, strip->name, sizeof(str));
str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str));
}
/* set text color - if colors (see above) are light, draw black text, otherwise draw white */
@ -470,7 +471,7 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i
rect.ymax = ymaxc;
/* add this string to the cache of texts to draw */
UI_view2d_text_cache_rectf(v2d, &rect, str, col);
UI_view2d_text_cache_rectf(v2d, &rect, str, str_len, col);
}
/* add frame extents to cache of text-strings to draw in pixelspace
@ -480,7 +481,8 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
{
const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
const char col[4] = {220, 220, 220, 255}; /* light gray */
char numstr[32] = "";
char numstr[32];
size_t numstr_len;
/* Always draw times above the strip, whereas sequencer drew below + above.
@ -490,12 +492,12 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
* while also preserving some accuracy, since we do use floats
*/
/* start frame */
BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start);
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, col);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start);
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
/* end frame */
BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end);
UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, col);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end);
UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
}
/* ---------------------- */

View File

@ -342,7 +342,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
{
float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect
float x1, x2, y1, y2;
char numstr[32];
unsigned int whichsel = 0;
x1 = seq->startdisp;
@ -401,17 +400,20 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
const char col[4] = {255, 255, 255, 255};
char numstr[32];
size_t numstr_len;
if (direction == SEQ_LEFTHANDLE) {
BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp);
x1 = rx1;
y1 -= 0.45f;
}
else {
BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
x1 = x2 - handsize_clamped * 0.75f;
y1 = y2 + 0.05f;
}
UI_view2d_text_cache_add(v2d, x1, y1, numstr, col);
UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col);
}
}
@ -526,6 +528,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
{
rctf rect;
char str[32 + FILE_MAX];
size_t str_len;
const char *name = seq->name + 2;
char col[4];
@ -534,67 +537,76 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
name = BKE_sequence_give_name(seq);
if (seq->type == SEQ_TYPE_META || seq->type == SEQ_TYPE_ADJUSTMENT) {
BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
}
else if (seq->type == SEQ_TYPE_SCENE) {
if (seq->scene) {
if (seq->scene_camera) {
BLI_snprintf(str, sizeof(str), "%s: %s (%s) | %d",
name, seq->scene->id.name + 2, ((ID *)seq->scene_camera)->name + 2, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s (%s) | %d",
name, seq->scene->id.name + 2, ((ID *)seq->scene_camera)->name + 2, seq->len);
}
else {
BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->scene->id.name + 2, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->scene->id.name + 2, seq->len);
}
}
else {
BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
}
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
if (seq->clip && strcmp(name, seq->clip->id.name + 2) != 0) {
BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->clip->id.name + 2, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->clip->id.name + 2, seq->len);
}
else {
BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
}
else if (seq->type == SEQ_TYPE_MASK) {
if (seq->mask && strcmp(name, seq->mask->id.name + 2) != 0) {
BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->mask->id.name + 2, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->mask->id.name + 2, seq->len);
}
else {
BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
}
else if (seq->type == SEQ_TYPE_MULTICAM) {
BLI_snprintf(str, sizeof(str), "Cam %s: %d",
name, seq->multicam_source);
str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d",
name, seq->multicam_source);
}
else if (seq->type == SEQ_TYPE_IMAGE) {
BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
}
else if (seq->type & SEQ_TYPE_EFFECT) {
BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (seq->sound)
BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->sound->name, seq->len);
else
BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
if (seq->sound) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->sound->name, seq->len);
}
else {
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
}
else if (seq->type == SEQ_TYPE_MOVIE) {
BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
}
else {
/* should never get here!, but might with files from future */
BLI_assert(0);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
name, seq->len);
}
if (seq->flag & SELECT) {
@ -612,7 +624,8 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
rect.ymin = y1;
rect.xmax = x2;
rect.ymax = y2;
UI_view2d_text_cache_rectf(v2d, &rect, str, col);
UI_view2d_text_cache_rectf(v2d, &rect, str, str_len, col);
}
/* draws a shaded strip, made from gradient + flat color + gradient */

View File

@ -238,22 +238,25 @@ void draw_motion_path_instance(Scene *scene,
for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
int frame = sfra + i;
char numstr[32];
size_t numstr_len;
float co[3];
/* only draw framenum if several consecutive highlighted points don't occur on same point */
if (i == 0) {
sprintf(numstr, " %d", frame);
numstr_len = sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
view3d_cached_text_draw_add(co, numstr, numstr_len,
0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
else if ((i >= stepsize) && (i < len - stepsize)) {
bMotionPathVert *mpvP = (mpv - stepsize);
bMotionPathVert *mpvN = (mpv + stepsize);
if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
sprintf(numstr, " %d", frame);
numstr_len = sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
view3d_cached_text_draw_add(co, numstr, numstr_len,
0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
}
}
@ -314,10 +317,12 @@ void draw_motion_path_instance(Scene *scene,
if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
char numstr[32];
size_t numstr_len;
sprintf(numstr, " %d", (sfra + i));
numstr_len = sprintf(numstr, " %d", (sfra + i));
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
view3d_cached_text_draw_add(co, numstr, numstr_len,
0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
}
}

View File

@ -2065,7 +2065,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* Draw names of bone */
if (arm->flag & ARM_DRAWNAMES) {
mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col);
view3d_cached_text_draw_add(vec, pchan->name, strlen(pchan->name), 10, 0, col);
}
/* Draw additional axes on the bone tail */
@ -2270,7 +2270,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
if (arm->flag & ARM_DRAWNAMES) {
mid_v3_v3v3(vec, eBone->head, eBone->tail);
glRasterPos3fv(vec);
view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col);
view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col);
}
/* Draw additional axes */
if (arm->flag & ARM_DRAWAXES) {

View File

@ -43,8 +43,12 @@
#include "DNA_world_types.h"
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
#include "BLI_listbase.h"
#include "BLI_link_utils.h"
#include "BLI_string.h"
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BKE_anim.h" /* for the where_on_path function */
#include "BKE_armature.h"
@ -742,11 +746,9 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
}
/* *********** text drawing for object/particles/armature ************* */
static ListBase CachedText[3];
static int CachedTextLevel = 0;
typedef struct ViewCachedString {
struct ViewCachedString *next, *prev;
struct ViewCachedString *next;
float vec[3];
union {
unsigned char ub[4];
@ -759,43 +761,61 @@ typedef struct ViewCachedString {
/* str is allocated past the end */
} ViewCachedString;
/* one arena for all 3 string lists */
static MemArena *g_v3d_strings_arena = NULL;
static ViewCachedString *g_v3d_strings[3] = {NULL, NULL, NULL};
static int g_v3d_string_level = -1;
void view3d_cached_text_draw_begin(void)
{
ListBase *strings = &CachedText[CachedTextLevel];
BLI_listbase_clear(strings);
CachedTextLevel++;
g_v3d_string_level++;
BLI_assert(g_v3d_string_level >= 0);
if (g_v3d_string_level == 0) {
BLI_assert(g_v3d_strings_arena == NULL);
}
}
void view3d_cached_text_draw_add(const float co[3],
const char *str,
const char *str, const size_t str_len,
short xoffs, short flag,
const unsigned char col[4])
{
int alloc_len = strlen(str) + 1;
ListBase *strings = &CachedText[CachedTextLevel - 1];
int alloc_len = str_len + 1;
/* TODO, replace with more efficient malloc, perhaps memarena per draw? */
ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
ViewCachedString *vos;
BLI_assert(str_len == strlen(str));
if (g_v3d_strings_arena == NULL) {
g_v3d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
}
vos = BLI_memarena_alloc(g_v3d_strings_arena, sizeof(ViewCachedString) + alloc_len);
BLI_LINKS_PREPEND(g_v3d_strings[g_v3d_string_level], vos);
BLI_addtail(strings, vos);
copy_v3_v3(vos->vec, co);
copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
vos->xoffs = xoffs;
vos->flag = flag;
vos->str_len = alloc_len - 1;
vos->str_len = str_len;
/* allocate past the end */
memcpy(++vos, str, alloc_len);
memcpy(vos + 1, str, alloc_len);
}
void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
ListBase *strings = &CachedText[CachedTextLevel - 1];
ViewCachedString *vos;
int tot = 0;
BLI_assert(g_v3d_string_level >= 0 && g_v3d_string_level <= 2);
/* project first and test */
for (vos = strings->first; vos; vos = vos->next) {
for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
mul_m4_v3(mat, vos->vec);
@ -840,7 +860,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
glDepthMask(0);
}
for (vos = strings->first; vos; vos = vos->next) {
for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
if (vos->sco[0] != IS_CLIPPED) {
const char *str = (char *)(vos + 1);
@ -859,7 +879,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
vos->str_len);
}
}
if (depth_write) {
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@ -876,11 +896,17 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
ED_view3d_clipping_enable();
}
}
if (strings->first)
BLI_freelistN(strings);
CachedTextLevel--;
g_v3d_strings[g_v3d_string_level] = NULL;
if (g_v3d_string_level == 0) {
if (g_v3d_strings_arena) {
BLI_memarena_free(g_v3d_strings_arena);
g_v3d_strings_arena = NULL;
}
}
g_v3d_string_level--;
}
/* ******************** primitive drawing ******************* */
@ -1605,7 +1631,10 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
float pos[3];
mul_v3_m4v3(pos, mat, track->bundle_pos);
view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, selected ? col_sel : col_unsel);
view3d_cached_text_draw_add(pos,
track->name, strlen(track->name),
10, V3D_CACHE_TEXT_GLOBALSPACE,
selected ? col_sel : col_unsel);
}
tracknr++;
@ -2780,6 +2809,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
Mesh *me = ob->data;
float v1[3], v2[3], v3[3], vmid[3], fvec[3];
char numstr[32]; /* Stores the measurement display text here */
size_t numstr_len;
const char *conv_float; /* Use a float conversion matching the grid size */
unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
float area; /* area of the face */
@ -2857,14 +2887,14 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
}
if (unit->system) {
bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
unit->system, B_UNIT_LENGTH, do_split, false);
numstr_len = bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
unit->system, B_UNIT_LENGTH, do_split, false);
}
else {
BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
}
view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
}
}
}
@ -2940,9 +2970,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_normalized_v3v3(no_a, no_b);
BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
}
}
}
@ -2959,14 +2989,15 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \
mul_v3_fl(vmid, 1.0f / (float)n); \
if (unit->system) { \
bUnit_AsString(numstr, sizeof(numstr), \
(double)(area * unit->scale_length * unit->scale_length), \
3, unit->system, B_UNIT_AREA, do_split, false); \
numstr_len = bUnit_AsString( \
numstr, sizeof(numstr), \
(double)(area * unit->scale_length * unit->scale_length), \
3, unit->system, B_UNIT_AREA, do_split, false); \
} \
else { \
BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
} \
view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \
} (void)0
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
@ -3082,9 +3113,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_v3v3v3(v1, v2, v3);
BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col);
}
}
}
@ -3100,6 +3131,7 @@ static void draw_em_indices(BMEditMesh *em)
BMVert *v;
int i;
char numstr[32];
size_t numstr_len;
float pos[3];
unsigned char col[4];
@ -3112,8 +3144,8 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
BLI_snprintf(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col);
}
i++;
}
@ -3124,9 +3156,9 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
BLI_snprintf(numstr, sizeof(numstr), "%d", i);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
mid_v3_v3v3(pos, e->v1->co, e->v2->co);
view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
i++;
}
@ -3138,8 +3170,8 @@ static void draw_em_indices(BMEditMesh *em)
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
BM_face_calc_center_mean(f, pos);
BLI_snprintf(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
i++;
}
@ -4484,6 +4516,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false;
GLint polygonmode[2];
char numstr[32];
size_t numstr_len;
unsigned char tcol[4] = {0, 0, 0, 255};
/* 1. */
@ -4831,28 +4864,32 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if ((part->draw & PART_DRAW_NUM || part->draw & PART_DRAW_HEALTH) &&
(v3d->flag2 & V3D_RENDER_OVERRIDE) == 0)
{
size_t numstr_len;
float vec_txt[3];
char *val_pos = numstr;
numstr[0] = '\0';
if (part->draw & PART_DRAW_NUM) {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
}
else {
BLI_snprintf(val_pos, sizeof(numstr), "%d", a);
numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a);
}
}
else {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health);
numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health);
}
}
/* in path drawing state.co is the end point */
/* use worldspace beause object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, state.co);
view3d_cached_text_draw_add(vec_txt, numstr, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
if (numstr[0]) {
/* in path drawing state.co is the end point */
/* use worldspace beause object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, state.co);
view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
}
}
}
}
@ -4944,10 +4981,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
float vec_txt[3];
BLI_snprintf(numstr, sizeof(numstr), "%i", a);
numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a);
/* use worldspace beause object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
view3d_cached_text_draw_add(vec_txt, numstr, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
}
}
}
@ -6630,7 +6668,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
/* when const color is set wirecolor is NULL - we could get the current color but
* with selection and group instancing its not needed to draw the text */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
view3d_cached_text_draw_add(v, axis_str[axis], 0, V3D_CACHE_TEXT_ASCII, ob_wire_col);
view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col);
}
}
glLineWidth(1.0f);
@ -7404,7 +7442,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* but, we also don't draw names for sets or duplicators */
if (dflag == 0) {
const float zero[3] = {0, 0, 0};
view3d_cached_text_draw_add(zero, ob->id.name + 2, 10, 0, ob_wire_col);
view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col);
}
}
/*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/

View File

@ -140,7 +140,9 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struc
void drawaxes(float size, char drawtype);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4]);
void view3d_cached_text_draw_add(const float co[3],
const char *str, const size_t str_len,
short xoffs, short flag, const unsigned char col[4]);
void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]);
bool check_object_draw_texture(struct Scene *scene, struct View3D *v3d, const char drawtype);