From 46deddcc62784dab47b1f14dda0d802f5f341b18 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Oct 2007 16:17:27 +0000 Subject: [PATCH] Image Stamping patch by Diego (and peach request)- stamps image info into metadata and optionally draws into the frame. This patch includes some changes I made... * use blenders bitmap fonts (rather then own fonts) * select font size * user interface layout changes * Marker as another image stamp option Also added some new API calls BMF_GetFontHeight(font); BMF_DrawStringBuf(...); - so we can draw text into an imbuf's image buffer. get_frame_marker(frame) - get the last marker from the frame. IMB_rectfill_area(...) - fill in an image buffer with a rectangle area of color. TODO - draw stamp info in 3d view, at the moment it just displays in the animation. --- intern/bmfont/BMF_Api.h | 22 +++ intern/bmfont/intern/BMF_Api.cpp | 11 ++ intern/bmfont/intern/BMF_BitmapFont.cpp | 90 +++++++++ intern/bmfont/intern/BMF_BitmapFont.h | 20 ++ source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_image.h | 1 + source/blender/blenkernel/intern/image.c | 191 +++++++++++++++++++- source/blender/blenloader/intern/readfile.c | 10 +- source/blender/blenpluginapi/iff.h | 1 + source/blender/imbuf/IMB_imbuf.h | 4 + source/blender/imbuf/intern/IMB_imginfo.h | 6 + source/blender/imbuf/intern/imginfo.c | 49 +++++ source/blender/imbuf/intern/png.c | 1 + source/blender/imbuf/intern/rectop.c | 53 ++++++ source/blender/imbuf/intern/thumbs.c | 14 +- source/blender/include/BSE_time.h | 1 + source/blender/makesdna/DNA_scene_types.h | 20 ++ source/blender/src/buttons_scene.c | 66 +++++++ source/blender/src/buttons_shading.c | 2 +- source/blender/src/drawview.c | 2 +- source/blender/src/editmesh_tools.c | 11 +- source/blender/src/edittime.c | 23 +++ source/blender/src/transform_constraints.c | 2 +- 23 files changed, 582 insertions(+), 20 deletions(-) diff --git a/intern/bmfont/BMF_Api.h b/intern/bmfont/BMF_Api.h index 5900ea85ec7..1b4a4ee3129 100644 --- a/intern/bmfont/BMF_Api.h +++ b/intern/bmfont/BMF_Api.h @@ -109,6 +109,11 @@ void BMF_GetStringBoundingBox(BMF_Font* font, char* str, float*llx, float *lly, */ void BMF_GetFontBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r); +/** + * Same as GetFontBoundingBox but only returns the height + */ +int BMF_GetFontHeight(BMF_Font* font); + /** * Convert the given @a font to a texture, and return the GL texture * ID of the texture. If the texture ID is bound, text can @@ -134,6 +139,23 @@ int BMF_GetFontTexture(BMF_Font* font); */ void BMF_DrawStringTexture(BMF_Font* font, char* string, float x, float y, float z); + /** + * Draw the given @a string at the point @a xpos, @a ypos using + * char and float buffers. + * + * @param string The c-string to draw. + * @param xpos The x coordinate to start drawing at. + * @param ypos The y coordinate to start drawing at. + * @param fgcol The forground color. + * @param bgcol The background color. + * @param buf Unsigned char image buffer, when NULL to not operate on it. + * @param fbuf float image buffer, when NULL to not operate on it. + * @param w image buffer width. + * @param h image buffer height. + */ +void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h); + + #ifdef __cplusplus } #endif diff --git a/intern/bmfont/intern/BMF_Api.cpp b/intern/bmfont/intern/BMF_Api.cpp index 176ef452fdc..eaa8ffb939d 100644 --- a/intern/bmfont/intern/BMF_Api.cpp +++ b/intern/bmfont/intern/BMF_Api.cpp @@ -164,6 +164,12 @@ void BMF_GetFontBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_ ((BMF_BitmapFont*)font)->GetFontBoundingBox(*xmin_r, *ymin_r, *xmax_r, *ymax_r); } +int BMF_GetFontHeight(BMF_Font* font) +{ + if (!font) return -1; + return ((BMF_BitmapFont*)font)->GetFontHeight(); +} + int BMF_GetFontTexture(BMF_Font* font) { if (!font) return -1; return ((BMF_BitmapFont*)font)->GetTexture(); @@ -173,3 +179,8 @@ void BMF_DrawStringTexture(BMF_Font* font, char *string, float x, float y, float if (!font) return; ((BMF_BitmapFont*)font)->DrawStringTexture(string, x, y, z); } + +void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h) { + if (!font) return; + ((BMF_BitmapFont*)font)->DrawStringBuf(str, posx, posy, col, buf, fbuf, w, h); +} diff --git a/intern/bmfont/intern/BMF_BitmapFont.cpp b/intern/bmfont/intern/BMF_BitmapFont.cpp index 8be4ff19a4f..99ded41007f 100644 --- a/intern/bmfont/intern/BMF_BitmapFont.cpp +++ b/intern/bmfont/intern/BMF_BitmapFont.cpp @@ -35,6 +35,11 @@ * Copyright (C) 2001 NaN Technologies B.V. */ + +#include + + + #include #ifdef HAVE_CONFIG_H @@ -115,6 +120,11 @@ void BMF_BitmapFont::GetFontBoundingBox(int & xMin, int & yMin, int & xMax, int yMax = m_fontData->ymax; } +int BMF_BitmapFont::GetFontHeight( void ) +{ + return m_fontData->ymax - m_fontData->ymin; +} + void BMF_BitmapFont::GetStringBoundingBox(char* str, float*llx, float *lly, float *urx, float *ury) { unsigned char c; @@ -229,3 +239,83 @@ void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z) } glEnd(); } + +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) + + +void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h) +{ + int x, y; + + if (buf==0 && fbuf==0) + return; + + /*offset for font*/ + posx -= m_fontData->xmin; + posy -= m_fontData->ymin; + + if (buf) { + unsigned char colch[3]; + unsigned char *max, *pixel; + unsigned char c; + + for (x=0; x<3; x++) { + colch[x] = FTOCHAR(col[x]); + } + + max = buf + (4 * (w * h)); + while ((c = (unsigned char) *str++)) { + BMF_CharData & cd = m_fontData->chars[c]; + if (cd.data_offset != -1) { + for (y = 0; y < cd.height; y++) { + unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y]; + for (x = cd.xorig; x < cd.width; x++) { + pixel = buf + 4 * (((posy + y) * w) + (posx + x)); + if ((pixel < max) && (pixel > buf)) { + int byteIdx = x/8; + int bitIdx = 7 - (x%8); + + if (chrRow[byteIdx]&(1<chars[c]; + if (cd.data_offset != -1) { + for (y = 0; y < cd.height; y++) { + unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y]; + for (x = cd.xorig; x < cd.width; x++) { + pixel = fbuf + 4 * (((posy + y - cd.yorig) * w) + (posx + x)); + if ((pixel < max) && (pixel > fbuf)) { + int byteIdx = x/8; + int bitIdx = 7 - (x%8); + + if (chrRow[byteIdx]&(1<r.stamp_font_id) { + case 1: /* tiny */ + font = BMF_GetFont(BMF_kHelveticaBold8); + break; + case 2: /* small */ + font = BMF_GetFont(BMF_kHelveticaBold10); + break; + case 3: /* medium */ + font = BMF_GetFont(BMF_kScreen12); + break; + case 0: /* large - default */ + font = BMF_GetFont(BMF_kScreen15); + break; + case 4: /* huge */ + font = BMF_GetFont(BMF_kHelveticaBold14); + break; + } + + font_height = BMF_GetFontHeight(font); + text_pad = BMF_GetStringWidth(font, " "); + + IMB_imginfo_change_field (ibuf, "File", G.sce); + if (G.scene->r.stamp & R_STAMP_DRAW) { + x = 1; + y = ibuf->y - font_height; + sprintf(text, "File: %s", G.sce); + text_width = BMF_GetStringWidth(font, text); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, G.sce, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + x = 1; + y -= font_height+1; + } + + + if (G.scene->r.stamp & R_STAMP_TIME) { + h= m= s= f= 0; + f = (int)(G.scene->r.cfra % G.scene->r.frs_sec); + s = (int)(G.scene->r.cfra / G.scene->r.frs_sec); + + if (s) { + m = (int)(s / 60); + s %= 60; + + if (m) { + h = (int)(m / 60); + m %= 60; + } + } + + if (G.scene->r.frs_sec < 100) + sprintf (infotext, "%02d:%02d:%02d.%02d", h, m, s, f); + else + sprintf (infotext, "%02d:%02d:%02d.%03d", h, m, s, f); + + IMB_imginfo_change_field (ibuf, "Time", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + sprintf (text, "Time %s", infotext); + text_width = BMF_GetStringWidth(font, text); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + x += text_width; + } + } + + if (G.scene->r.stamp & R_STAMP_FRAME) { + sprintf (infotext, "%i", G.scene->r.cfra); + IMB_imginfo_change_field (ibuf, "Frame", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + sprintf (text, " Frame %s", infotext); + text_width = BMF_GetStringWidth(font, text); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + x += BMF_GetStringWidth(font, text); + } + } + + if (G.scene->r.stamp & R_STAMP_DATE) { +#ifdef WIN32 + _strdate (sdate); + sprintf (infotext, "%s", sdate); +#else + t = time (NULL); + tl = localtime (&t); + sprintf (infotext, "%02d-%02d-%02d", tl->tm_mon+1, tl->tm_mday, tl->tm_year-100); +#endif /* WIN32 */ + IMB_imginfo_change_field (ibuf, "Date", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + x = 1; + y = 1; + sprintf (text, "Date %s", infotext); + text_width = BMF_GetStringWidth(font, text); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + x += text_width; + } + } + + if (G.scene->r.stamp & R_STAMP_CAMERA) { + sprintf(infotext, ((Camera *) G.scene->camera)->id.name+2); + IMB_imginfo_change_field (ibuf, "Camera", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + sprintf (text, "Camera: %s", infotext); + text_width = BMF_GetStringWidth(font, text); + x = (ibuf->x/2) - (BMF_GetStringWidth(font, text)/2); + y = 1; + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + } + } + + if (G.scene->r.stamp & R_STAMP_SCENE) { + strcpy(infotext, G.scene->id.name+2); + IMB_imginfo_change_field (ibuf, "Scene", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + sprintf (text, "Scene: %s", infotext); + text_width = BMF_GetStringWidth(font, text); + x = ibuf->x - (BMF_GetStringWidth(font, text)+1+text_pad); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + } + } + + if (G.scene->r.stamp & R_STAMP_NOTE) { + IMB_imginfo_change_field (ibuf, "Note", G.scene->r.stamp_udata); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + x = 1; + y = font_height+1; + text_width = BMF_GetStringWidth(font, G.scene->r.stamp_udata); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, G.scene->r.stamp_udata, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + } + } + + if (G.scene->r.stamp & R_STAMP_MARKER) { + TimeMarker *marker = get_frame_marker(CFRA); + + if (marker) strcpy(infotext, marker->name); + else strcpy(infotext, "None"); + + IMB_imginfo_change_field (ibuf, "Marker", infotext); + + if (G.scene->r.stamp & R_STAMP_DRAW) { + sprintf (text, "Marker: %s", infotext); + x = 1; + y = ibuf->y - (font_height+1)*3; + text_width = BMF_GetStringWidth(font, text); + IMB_rectfill_area(ibuf, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, text, x, y, G.scene->r.fg_stamp, (unsigned char *)ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y); + } + } +} int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quality) { @@ -830,7 +1014,10 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali } BLI_make_existing_file(name); - + + if(G.scene->r.scemode & R_STAMP_INFO) + BKE_stamp(ibuf); + ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); if (ok == 0) { perror(name); @@ -1254,7 +1441,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) BLI_convertstringcode(str, G.sce, cfra); /* read ibuf */ - ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer); + ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer|IB_imginfo); } if (ibuf) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 487cce9e44f..a5859311470 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6764,7 +6764,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ((ArmatureModifierData*)md)->deformflag |= ARM_DEF_B_BONE_REST; } - + if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 5)) { + /* foreground color needs to be somthing other then black */ + Scene *sce; + for(sce= main->scene.first; sce; sce=sce->id.next) { + sce->r.fg_stamp[0] = sce->r.fg_stamp[1] = sce->r.fg_stamp[2] = 0.8; + } + } + + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/blenpluginapi/iff.h b/source/blender/blenpluginapi/iff.h index 8e5b538eda6..f63f753e553 100644 --- a/source/blender/blenpluginapi/iff.h +++ b/source/blender/blenpluginapi/iff.h @@ -208,6 +208,7 @@ LIBEXPORT void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height); LIBEXPORT void IMB_rectfill(struct ImBuf *drect, float col[4]); +LIBEXPORT void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2); #endif /* IFF_H */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 2ca21e548c4..4d91a82a58f 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -545,6 +545,10 @@ void IMB_freezbuffloatImBuf(struct ImBuf * ibuf); * @attention Defined in rectop.c */ void IMB_rectfill(struct ImBuf *drect, float col[4]); +void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2); + +/* defined in imginfo.c */ +int IMB_imginfo_change_field(struct ImBuf *img, const char *key, const char *field); /* exported for image tools in blender, to quickly allocate 32 bits rect */ short imb_addrectImBuf(struct ImBuf * ibuf); diff --git a/source/blender/imbuf/intern/IMB_imginfo.h b/source/blender/imbuf/intern/IMB_imginfo.h index c8e9005619c..e82cc5f32af 100644 --- a/source/blender/imbuf/intern/IMB_imginfo.h +++ b/source/blender/imbuf/intern/IMB_imginfo.h @@ -74,6 +74,12 @@ int IMB_imginfo_get_field(struct ImBuf* img, const char* key, char* value, int l */ int IMB_imginfo_add_field(struct ImBuf* img, const char* key, const char* field); +/** delete the key/field par in the ImgInfo struct. + * @param img - the ImBuf that contains the image data + * @param key - the key of the field + * @return - 1 (true) if delete the key/field, 0 (false) otherwise + */ +int IMB_imginfo_del_field(struct ImBuf *img, const char *key); #endif /* _IMB_IMGINFO_H */ diff --git a/source/blender/imbuf/intern/imginfo.c b/source/blender/imbuf/intern/imginfo.c index 59fbd2f7200..37bde9e5ac3 100644 --- a/source/blender/imbuf/intern/imginfo.c +++ b/source/blender/imbuf/intern/imginfo.c @@ -107,3 +107,52 @@ int IMB_imginfo_add_field(struct ImBuf* img, const char* key, const char* field) return 1; } +int IMB_imginfo_del_field(struct ImBuf *img, const char *key) +{ + ImgInfo *p, *p1; + + if ((!img) || (!img->img_info)) + return (0); + + p = img->img_info; + p1 = NULL; + while (p) { + if (!strcmp (key, p->key)) { + if (p1) + p1->next = p->next; + else + img->img_info = p->next; + + MEM_freeN(p->key); + MEM_freeN(p->value); + MEM_freeN(p); + return (1); + } + p1 = p; + p = p->next; + } + return (0); +} + +int IMB_imginfo_change_field(struct ImBuf *img, const char *key, const char *field) +{ + ImgInfo *p; + + if (!img) + return (0); + + if (!img->img_info) + return (IMB_imginfo_add_field (img, key, field)); + + p = img->img_info; + while (p) { + if (!strcmp (key, p->key)) { + MEM_freeN (p->value); + p->value = BLI_strdup (field); + return (1); + } + p = p->next; + } + + return (IMB_imginfo_add_field (img, key, field)); +} diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index bb48ff71bff..c77ff7ea56f 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -236,6 +236,7 @@ short imb_savepng(struct ImBuf *ibuf, char *name, int flags) iptr = ibuf->img_info; num_text = 0; while (iptr) { + imginfo[num_text].compression = PNG_TEXT_COMPRESSION_NONE; imginfo[num_text].key = iptr->key; imginfo[num_text].text = iptr->value; diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 85c5e07bb8e..55cd4b9b6a1 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -517,3 +517,56 @@ void IMB_rectfill(struct ImBuf *drect, float col[4]) } } +/* maybe we should use BKE_utildefines.h */ +#define FTOCHAR(val) (val<=0.0f ? 0: (val>=1.0f ? 255: (char)(255.99f*val))) +#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) +#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } +void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2) +{ + int i, j; + + if ((!ibuf) || (!col)) + return; + + /* sanity checks for coords */ + CLAMP(x1, 0, ibuf->x); + CLAMP(x2, 0, ibuf->x); + CLAMP(y1, 0, ibuf->y); + CLAMP(y2, 0, ibuf->y); + + if (x1>x2) SWAP(int,x1,x2); + if (y1>y2) SWAP(int,y1,y2); + if (x1==x2 || y1==y2) return; + + if (ibuf->rect) { + unsigned char *img, *pixel; + unsigned char chr, chg, chb; + + chr = FTOCHAR(col[0]); + chg = FTOCHAR(col[1]); + chb = FTOCHAR(col[2]); + + img = (unsigned char *) ibuf->rect; + for (j = 0; j < y2-y1; j++) { + for (i = 0; i < x2-x1; i++) { + pixel = img + 4 * (((y1 + j) * ibuf->x) + (x1 + i)); + pixel[0] = chr; + pixel[1] = chg; + pixel[2] = chb; + } + } + } + + if (ibuf->rect_float) { + float *img, *pixel; + img = ibuf->rect_float; + for (j = 0; j < y2-y1; j++) { + for (i = 0; i < x2-x1; i++) { + pixel = img + 4 * (((y1 + j) * ibuf->x) + (x1 + i)); + pixel[0] = col[0]; + pixel[1] = col[1]; + pixel[2] = col[2]; + } + } + } +} diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 493b0968f55..131d2ef38f7 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -281,7 +281,7 @@ ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, Thumb if (THB_SOURCE_IMAGE == source) { BLI_getwdN(wdir); chdir(dir); - img = IMB_loadiffname(file, IB_rect); + img = IMB_loadiffname(file, IB_rect | IB_imginfo); if (img != NULL) { stat(file, &info); sprintf(mtime, "%ld", info.st_mtime); @@ -324,13 +324,13 @@ ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, Thumb IMB_scaleImBuf(img, ex, ey); } sprintf(desc, "Thumbnail for %s", uri); - IMB_imginfo_add_field(img, "Description", desc); - IMB_imginfo_add_field(img, "Software", "Blender"); - IMB_imginfo_add_field(img, "Thumb::URI", uri); - IMB_imginfo_add_field(img, "Thumb::MTime", mtime); + IMB_imginfo_change_field(img, "Description", desc); + IMB_imginfo_change_field(img, "Software", "Blender"); + IMB_imginfo_change_field(img, "Thumb::URI", uri); + IMB_imginfo_change_field(img, "Thumb::MTime", mtime); if (THB_SOURCE_IMAGE == source) { - IMB_imginfo_add_field(img, "Thumb::Image::Width", cwidth); - IMB_imginfo_add_field(img, "Thumb::Image::Height", cheight); + IMB_imginfo_change_field(img, "Thumb::Image::Width", cwidth); + IMB_imginfo_change_field(img, "Thumb::Image::Height", cheight); } img->ftype = PNG; img->depth = 32; diff --git a/source/blender/include/BSE_time.h b/source/blender/include/BSE_time.h index c7f235bccbd..d5cff9f5e5f 100644 --- a/source/blender/include/BSE_time.h +++ b/source/blender/include/BSE_time.h @@ -55,6 +55,7 @@ void add_marker_to_cfra_elem(struct ListBase *lb, struct TimeMarker *marker, sho void make_marker_cfra_list(struct ListBase *lb, short only_sel); void draw_markers_timespace(int lines); +TimeMarker *get_frame_marker(int frame); /* ******** Animation - Preview Range ************* */ void anim_previewrange_set(void); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2ba5ef5437c..56b44c3ec97 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -278,6 +278,16 @@ typedef struct RenderData { /* paths to backbufffer, output, ftype */ char backbuf[160], pic[160], ftype[160]; + /* stamps flags. */ + int stamp; + short stamp_font_id, pad3; /* select one of blenders bitmap fonts */ + + /* stamp info user data. */ + char stamp_udata[160]; + + /* foreground/background color. */ + float fg_stamp[4]; + float bg_stamp[4]; } RenderData; @@ -517,7 +527,17 @@ typedef struct Scene { #define R_COMP_FREE 0x0800 #define R_NO_IMAGE_LOAD 0x1000 #define R_NO_TEX 0x2000 +#define R_STAMP_INFO 0x4000 +/* r->stamp */ +#define R_STAMP_TIME 0x0001 +#define R_STAMP_FRAME 0x0002 +#define R_STAMP_DATE 0x0004 +#define R_STAMP_CAMERA 0x0008 +#define R_STAMP_SCENE 0x0010 +#define R_STAMP_NOTE 0x0020 +#define R_STAMP_DRAW 0x0040 /* draw in the image */ +#define R_STAMP_MARKER 0x0080 /* alphamode */ #define R_ADDSKY 0 diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index c319485cb0f..939c3b561e3 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1526,6 +1526,71 @@ static void render_panel_ffmpeg_audio(void) } #endif +static void render_panel_stamp(void) +{ + uiBlock *block; + int yofs, xofs; + + + block= uiNewBlock (&curarea->uiblocks, "render_panel_stamp", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed ("Format", "Render"); + if(uiNewPanel (curarea, block, "Stamp", "Render", 960, 0, 318, 204)==0) return; + + if (G.scene->r.scemode & R_STAMP_INFO) { + yofs = 0; + xofs = 550;uiBlockBeginAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, R_STAMP_NOTE, B_REDR, "Note", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp user data"); + uiDefBut(block, TEX, B_NOP, "", xofs+100, yofs, 200, 19, &G.scene->r.stamp_udata, 0.0, 128.0, 100, 0, "User Note"); + uiBlockEndAlign(block); + yofs += 30; /* gap */ + + + yofs += 100; + // Order is important for alligning ... grr + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, R_STAMP_SCENE, B_REDR, "Scene", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp scene name"); + yofs -= 20; + uiDefButBitI(block, TOG, R_STAMP_CAMERA, B_REDR, "Camera", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp camera name"); + yofs -= 20; + uiDefButBitI(block, TOG, R_STAMP_DATE, B_REDR, "Date", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp date"); + yofs -= 20; + uiDefButBitI(block, TOG, R_STAMP_TIME, B_REDR, "Time", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp time (HH:MM:SS)"); + yofs -= 20; + uiDefButBitI(block, TOG, R_STAMP_FRAME, B_REDR, "Frame", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp frame number"); + yofs -= 20; + uiDefButBitI(block, TOG, R_STAMP_MARKER, B_REDR, "Marker", xofs, yofs, 100, 19, &G.scene->r.stamp, 0, 0, 0, 0, "Stamp the last marker"); + uiBlockEndAlign(block); + yofs += 100; + + /* draw font selector */ + if (G.scene->r.stamp & R_STAMP_DRAW) { + uiDefButS(block, MENU, B_REDR, "Stamp Font Size%t|Tiny Text%x1|Small Text%x2|Medium Text%x3|Large Text%x0|Extra Large Text%x4|", + xofs+110, yofs, 190, 19, &G.scene->r.stamp_font_id, 0, 0, 0, 0, "Choose rendering engine"); + + /* draw fg/bg next to the scene */ + yofs -= 25; + uiDefBut(block, LABEL, 0, "Text Color", xofs+110, yofs, 80, 19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Background", xofs+205, yofs, 80, 19, 0, 0, 0, 0, 0, ""); + yofs -= 20; + uiDefButF(block, COL, B_NOP, "", xofs+110, yofs, 90, 19, G.scene->r.fg_stamp, 0, 0, 0, 0, "Foreground text color"); + uiDefButF(block, COL, B_NOP, "", xofs+210, yofs, 90, 19, G.scene->r.bg_stamp, 0, 0, 0, 0, "Background color"); + yofs += 75; + } else { + yofs += 30; + } + + uiDefButBitS(block, TOG, R_STAMP_INFO, B_REDR, "Enable Stamp", xofs, yofs, 100, 20, &G.scene->r.scemode, 0, 0, 0, 0, "Disable stamp info in images metadata"); + uiDefButBitI(block, TOG, R_STAMP_DRAW, B_REDR, "Draw Stamp", xofs+110, yofs, 190, 20, &G.scene->r.stamp, 0, 0, 0, 0, "Draw the stamp info into each frame"); + yofs += 20; + } + else { + uiDefButBitS(block, TOG, R_STAMP_INFO, B_REDR, "Enable Stamp", xofs, 142, 100, 20, &G.scene->r.scemode, 0, 0, 0, 0, "Enable stamp info to image metadata"); + yofs += 20; + uiDefBut(block, LABEL, 0, "", xofs, yofs, 300, 19, 0, 0, 0, 0, 0, ""); + } +} static void render_panel_format(void) { @@ -1927,6 +1992,7 @@ void render_panels() render_panel_bake(); render_panel_format(); + render_panel_stamp(); #ifdef WITH_FFMPEG if (G.scene->r.imtype == R_FFMPEG) { render_panel_ffmpeg_video(); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index e5026f6f64e..56c8d60bf5b 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -3377,7 +3377,7 @@ static void material_panel_tramir(Material *ma) uiBlockBeginAlign(block); uiDefButF(block, NUM, B_MATPRV, "Filter:", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->filter), 0.0, 1.0, 10, 0, "Amount to blend in the material's diffuse colour in raytraced transparency (simulating absorption)"); + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->filter), 0.0, 1.0, 10, 0, "Amount to blend in the material's diffuse color in raytraced transparency (simulating absorption)"); uiDefButF(block, NUMSLI, B_MATPRV, "Limit: ", X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->tx_limit), 0.0, 100.0, 10, 2, "Maximum depth for light to travel through the transparent material before becoming fully filtered (0.0 is disabled)"); uiDefButF(block, NUMSLI, B_MATPRV, "Falloff: ", diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index d67df1e0e97..9777415fc0a 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -1021,7 +1021,7 @@ static void drawviewborder(void) BIF_ThemeColor(TH_WIRE); glRectf(x1, y1, x2, y2); - /* camera name - draw in highlighted text colour */ + /* camera name - draw in highlighted text color */ if (ca && (ca->flag & CAM_SHOWNAME)) { BIF_ThemeColor(TH_TEXT_HI); glRasterPos2f(x1, y1-15); diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 56db0ea7016..a68fca3b294 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -198,10 +198,10 @@ void convert_to_triface(int direction) int removedoublesflag(short flag, short automerge, float limit) /* return amount */ { /* - flag - Test with vert->flags - weld - Alternative operation, merge unselected into selected. - Used for "Auto Weld" mode. warning. - limit - Quick manhattan distance between verts. + flag - Test with vert->flags + automerge - Alternative operation, merge unselected into selected. + Used for "Auto Weld" mode. warning. + limit - Quick manhattan distance between verts. */ EditMesh *em = G.editMesh; @@ -211,7 +211,6 @@ int removedoublesflag(short flag, short automerge, float limit) /* return amoun EditFace *efa, *nextvl; xvertsort *sortblock, *sb, *sb1; struct facesort *vlsortblock, *vsb, *vsb1; - float dist; int a, b, test, amount; if(multires_test()) return 0; @@ -253,7 +252,7 @@ int removedoublesflag(short flag, short automerge, float limit) /* return amoun for(b=a+1; bf & 128)==0; b++, sb1++) { if(sb1->x - sb->x > limit) break; - /* when welding, only allow selected-> unselected*/ + /* when automarge, only allow unselected->selected */ v1= sb1->v1; if( (v1->f & 128)==0 ) { if ((eve->f & flag)==0 && (v1->f & flag)==1) { diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index d9981f58ac2..280c69e2719 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -103,6 +103,8 @@ void add_marker(int frame) BIF_undo_push("Add Marker"); } + + /* remove selected TimeMarkers */ void remove_marker(void) { @@ -733,6 +735,27 @@ void nextprev_timeline_key(short dir) } } +/* return the current marker for this frame, +we can have more then 1 marker per frame, this just returns the first :/ */ +TimeMarker *get_frame_marker(int frame) +{ + TimeMarker *marker, *best_marker = NULL; + int best_frame = -MAXFRAME*2; + for (marker= G.scene->markers.first; marker; marker= marker->next) { + if (marker->frame==frame) { + return marker; + } + + if ( marker->frame > best_frame && marker->frame < frame) { + best_marker = marker; + best_frame = marker->frame; + } + } + + return best_marker; +} + + void timeline_frame_to_center(void) { float dtime; diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 0147435965d..ad48d3cc919 100644 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -850,7 +850,7 @@ static void setNearestAxis2d(TransInfo *t) ival[1]= t->imval[1]; /* no correction needed... just use whichever one is lower */ - if ( abs(mval[0]-ival[0]) > abs(mval[1]-ival[1]) ) { + if ( abs(mval[0]-ival[0]) < abs(mval[1]-ival[1]) ) { t->con.mode |= CON_AXIS1; sprintf(t->con.text, " along Y axis"); }