From 253432bfc7c2a1dae224a03fb3055de19743ec67 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 20 Dec 2006 17:57:56 +0000 Subject: The Big Image refactor! Please read: http://www.blender3d.org/cms/Imaging.834.0.html Or in short: - adding MultiLayer Image support - recoded entire Image API - better integration of movie/sequence Images Was a whole load of work... went down for a week to do this. So, will need a lot of testing! Will be in irc all evening. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 4 +- source/blender/blenkernel/BKE_image.h | 116 +- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/BKE_utildefines.h | 4 +- source/blender/blenkernel/intern/colortools.c | 44 +- source/blender/blenkernel/intern/image.c | 1376 +++++++++++++++----- source/blender/blenkernel/intern/library.c | 33 +- source/blender/blenkernel/intern/node.c | 61 +- source/blender/blenkernel/intern/node_composite.c | 567 ++++---- source/blender/blenkernel/intern/packedFile.c | 11 +- source/blender/blenkernel/intern/scene.c | 1 + source/blender/blenkernel/intern/texture.c | 32 +- source/blender/blenlib/BLI_blenlib.h | 4 +- source/blender/blenlib/intern/gsqueue.c | 9 +- source/blender/blenlib/intern/util.c | 4 +- source/blender/blenloader/intern/readfile.c | 215 ++- source/blender/imbuf/IMB_imbuf.h | 2 + source/blender/imbuf/IMB_imbuf_types.h | 34 +- source/blender/imbuf/intern/allocimbuf.c | 23 +- source/blender/imbuf/intern/divers.c | 30 +- source/blender/imbuf/intern/filter.c | 25 + .../blender/imbuf/intern/openexr/openexr_api.cpp | 402 +++++- .../blender/imbuf/intern/openexr/openexr_multi.h | 23 +- source/blender/imbuf/intern/readimage.c | 2 +- source/blender/imbuf/intern/rectop.c | 2 + source/blender/include/BIF_butspace.h | 2 + source/blender/include/BIF_drawimage.h | 10 + source/blender/include/BIF_editsima.h | 3 + source/blender/include/BIF_renderwin.h | 1 + source/blender/include/BIF_space.h | 1 + source/blender/include/BIF_writeimage.h | 2 +- source/blender/include/BSE_filesel.h | 8 +- source/blender/include/BSE_node.h | 8 + source/blender/include/blendef.h | 10 +- source/blender/include/butspace.h | 32 +- source/blender/makesdna/DNA_image_types.h | 47 +- source/blender/makesdna/DNA_node_types.h | 1 + source/blender/makesdna/DNA_packedFile_types.h | 1 + source/blender/makesdna/DNA_scene_types.h | 7 +- source/blender/makesdna/DNA_space_types.h | 55 +- source/blender/makesdna/DNA_texture_types.h | 26 +- source/blender/makesdna/DNA_view3d_types.h | 5 +- source/blender/python/api2_2x/Draw.c | 32 +- source/blender/python/api2_2x/Image.c | 158 +-- source/blender/python/api2_2x/Texture.c | 62 +- source/blender/python/api2_2x/sceneRender.c | 18 +- source/blender/render/extern/include/RE_pipeline.h | 11 +- source/blender/render/intern/include/texture.h | 5 +- .../blender/render/intern/source/convertblender.c | 2 +- source/blender/render/intern/source/envmap.c | 64 +- source/blender/render/intern/source/imagetexture.c | 863 ++++++------ source/blender/render/intern/source/pipeline.c | 424 ++++-- source/blender/render/intern/source/rendercore.c | 35 +- source/blender/render/intern/source/texture.c | 119 +- source/blender/src/butspace.c | 23 +- source/blender/src/buttons_scene.c | 22 +- source/blender/src/buttons_shading.c | 996 +++++++++----- source/blender/src/drawimage.c | 516 ++++---- source/blender/src/drawmesh.c | 81 +- source/blender/src/drawnode.c | 182 ++- source/blender/src/drawview.c | 282 +--- source/blender/src/editnode.c | 111 +- source/blender/src/editobject.c | 10 +- source/blender/src/editscreen.c | 28 +- source/blender/src/editsima.c | 403 ++++-- source/blender/src/edittime.c | 3 + source/blender/src/filesel.c | 161 ++- source/blender/src/header_filesel.c | 4 + source/blender/src/header_image.c | 270 +++- source/blender/src/header_info.c | 17 +- source/blender/src/header_node.c | 7 +- source/blender/src/header_time.c | 4 + source/blender/src/headerbuttons.c | 11 +- source/blender/src/imagepaint.c | 121 +- source/blender/src/interface.c | 30 +- source/blender/src/interface_icons.c | 6 +- source/blender/src/meshtools.c | 10 +- source/blender/src/previewrender.c | 2 + source/blender/src/renderwin.c | 61 +- source/blender/src/space.c | 39 +- source/blender/src/toets.c | 7 +- source/blender/src/toolbox.c | 5 +- source/blender/src/verse_object.c | 2 +- source/blender/src/writeimage.c | 101 +- source/blender/yafray/intern/yafray_Render.h | 1 - 86 files changed, 5424 insertions(+), 3131 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 71ede8820db..e7029a01c09 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 242 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 53097b915f0..e78882220a9 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -31,7 +31,7 @@ struct CurveMapping; struct CurveMap; -struct Image; +struct ImBuf; struct rctf; struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); @@ -53,7 +53,7 @@ float curvemapping_evaluateF(struct CurveMapping *cumap, int cur, float value void curvemapping_evaluate3F(struct CurveMapping *cumap, float *vecout, const float *vecin); void curvemapping_evaluateRGBF(struct CurveMapping *cumap, float *vecout, const float *vecin); void curvemapping_evaluate_premulRGBF(struct CurveMapping *cumap, float *vecout, const float *vecin); -void curvemapping_do_image(struct CurveMapping *cumap, struct Image *ima); +void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf); void curvemapping_premultiply(struct CurveMapping *cumap, int restore); int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 98a93611204..1acaf004fb9 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -43,28 +43,108 @@ struct ImBuf; struct Tex; struct anim; -void free_image(struct Image *me); -void free_image_preview(struct Image *ima); -void free_image_buffers(struct Image *ima); -struct Image *add_image(char *name); -void free_unused_animimages(void); -struct Image *new_image(int width, int height, char *name, short uvtestgrid); - -int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); -void BKE_makepicstring(char *string, char *base, int frame, int imtype); -void BKE_add_image_extension(char *string, int imtype); -int BKE_imtype_is_movie(int imtype); +/* call from library */ +void free_image(struct Image *me); + +int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); +void BKE_makepicstring(char *string, char *base, int frame, int imtype); +void BKE_add_image_extension(char *string, int imtype); +int BKE_ftype_to_imtype(int ftype); +int BKE_imtype_to_ftype(int imtype); +int BKE_imtype_is_movie(int imtype); struct anim *openanim(char * name, int flags); -void ima_ibuf_is_nul(struct Tex *tex, struct Image *ima); -void load_image(struct Image * ima, int flags, char *relabase, int framenum); -void converttopremul(struct ImBuf *ibuf); -void image_de_interlace(struct Image *ima, int odd); + +void converttopremul(struct ImBuf *ibuf); +void image_de_interlace(struct Image *ima, int odd); -void tag_image_time(struct Image *ima); -void free_old_images(void); +void tag_image_time(struct Image *ima); +void free_old_images(void); + +/* ********************************** NEW IMAGE API *********************** */ + +/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ +/* should be used in conjunction with an ID * to Image. */ +struct ImageUser; +struct RenderPass; +struct RenderResult; + +/* ima->source; where image comes from */ +#define IMA_SRC_CHECK 0 +#define IMA_SRC_FILE 1 +#define IMA_SRC_SEQUENCE 2 +#define IMA_SRC_MOVIE 3 +#define IMA_SRC_GENERATED 4 +#define IMA_SRC_VIEWER 5 + +/* ima->type, how to handle/generate it */ +#define IMA_TYPE_IMAGE 0 +#define IMA_TYPE_MULTILAYER 1 + /* generated */ +#define IMA_TYPE_UV_TEST 2 +#define IMA_TYPE_VERSE 3 + /* viewers */ +#define IMA_TYPE_R_RESULT 4 +#define IMA_TYPE_COMPOSITE 5 + +/* ima->ok */ +#define IMA_OK 1 +#define IMA_OK_LOADED 2 + +/* signals */ + /* reload only frees, doesn't read until image_get_ibuf() called */ +#define IMA_SIGNAL_RELOAD 0 +#define IMA_SIGNAL_FREE 1 + /* pack signals are executed */ +#define IMA_SIGNAL_PACK 2 +#define IMA_SIGNAL_REPACK 3 +#define IMA_SIGNAL_UNPACK 4 + /* source changes, from image to sequence or movie, etc */ +#define IMA_SIGNAL_SRC_CHANGE 5 + /* image-user gets a new image, check settings */ +#define IMA_SIGNAL_USER_NEW_IMAGE 6 + +/* depending Image type, and (optional) ImageUser setting it returns ibuf */ +/* always call to make signals work */ +struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); + +/* returns existing Image when filename/type is same */ +struct Image *BKE_add_image_file(const char *name); + +/* adds image, adds ibuf, generates color or pattern */ +struct Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid); + +/* for reload, refresh, pack */ +void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal); + +/* ensures an Image exists for viewing nodes or render */ +struct Image *BKE_image_verify_viewer(int type, const char *name); + +/* force an ImBuf to become part of Image */ +void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); + +/* called on frame change or before render */ +void BKE_image_user_calc_imanr(struct ImageUser *iuser, int cfra, int fieldnr); + +/* fix things in ImageUser when new image gets assigned */ +void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); + +/* sets index offset for multilayer files */ +struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); + +/* for multilayer images as well as for render-viewer */ +struct RenderResult *BKE_image_get_renderresult(struct Image *ima); + +/* goes over all textures that use images */ +void BKE_image_free_all_textures(void); + +/* does one image! */ +void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame); + +/* does all images with type MOVIE or SEQUENCE */ +void BKE_image_all_free_anim_ibufs(int except_frame); -void free_all_imagetextures(void); +void BKE_image_memorypack(struct Image *ima); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index c51ebe25226..cc6d15f7bcb 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -66,6 +66,7 @@ struct ID *find_id(char *type, char *name); void clear_id_newpoins(void); void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr); +void IMAnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID *link, short *nr); void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype); #endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index f5fe91920b7..232a2a2cd9e 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -42,10 +42,12 @@ #define TRUE 1 #endif -/* also fill in structs itself, dna cannot handle defines, duplicate in blendef.h still */ +/* these values need to be hardcoded in structs, dna does not recognize defines */ +/* also defined in DNA_space_types.h */ #ifndef FILE_MAXDIR #define FILE_MAXDIR 160 #define FILE_MAXFILE 80 +#define FILE_MAX 240 #endif #define ELEM(a, b, c) ( (a)==(b) || (a)==(c) ) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 93238137f95..6249bb2f21b 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -43,6 +43,7 @@ #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_ipo.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_utildefines.h" @@ -623,30 +624,43 @@ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) -void curvemapping_do_image(CurveMapping *cumap, Image *ima) +void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { int pixel; - if(ima==NULL || ima->ibuf==NULL) + if(ibuf==NULL) return; - if(ima->ibuf->rect_float==NULL) - IMB_float_from_rect(ima->ibuf); - else if(ima->ibuf->rect==NULL) - imb_addrectImBuf(ima->ibuf); + if(ibuf->rect_float==NULL) + IMB_float_from_rect(ibuf); + else if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); curvemapping_premultiply(cumap, 0); - if(ima->ibuf->rect_float && ima->ibuf->rect) { - float *pixf= ima->ibuf->rect_float; + if(ibuf->rect_float && ibuf->rect) { + float *pixf= ibuf->rect_float; float col[3]; - char *pixc= (char *)ima->ibuf->rect; + int stride= 4; + char *pixc= (char *)ibuf->rect; - for(pixel= ima->ibuf->x*ima->ibuf->y; pixel>0; pixel--, pixf+=4, pixc+=4) { - curvemapping_evaluate_premulRGBF(cumap, col, pixf); - pixc[0]= FTOCHAR(col[0]); - pixc[1]= FTOCHAR(col[1]); - pixc[2]= FTOCHAR(col[2]); - pixc[3]= FTOCHAR(pixf[3]); + if(ibuf->channels) + stride= ibuf->channels; + + for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pixf+=stride, pixc+=4) { + if(stride<3) { + col[0]= curvemap_evaluateF(cumap->cm, *pixf); + pixc[1]= pixc[2]= pixc[3]= pixc[0]= FTOCHAR(col[0]); + } + else { + curvemapping_evaluate_premulRGBF(cumap, col, pixf); + pixc[0]= FTOCHAR(col[0]); + pixc[1]= FTOCHAR(col[1]); + pixc[2]= FTOCHAR(col[2]); + if(stride>3) + pixc[3]= FTOCHAR(pixf[3]); + else + pixc[3]= 255; + } } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cf19d64ca03..b8a6ebf8928 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2,15 +2,12 @@ * * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * 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 @@ -26,9 +23,9 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation, 2006 * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #include @@ -47,85 +44,278 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "intern/openexr/openexr_multi.h" #include "DNA_image_types.h" -#include "DNA_texture_types.h" #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_threads.h" #include "BKE_bmfont.h" -#include "BKE_packedFile.h" -#include "BKE_library.h" #include "BKE_global.h" -#include "BKE_main.h" #include "BKE_icons.h" #include "BKE_image.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_packedFile.h" #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "PIL_time.h" +#include "RE_pipeline.h" + /* bad level; call to free_realtime_image */ #include "BKE_bad_level_calls.h" -void free_image_buffers(Image *ima) +/* max int, to indicate we don't store sequences in ibuf */ +#define IMA_NO_INDEX 0x7FEFEFEF + +/* quick lookup: supports 1 million frames, thousand passes */ +#define IMA_MAKE_INDEX(frame, index) ((frame)<<10)+index +#define IMA_INDEX_FRAME(index) (index>>10) + +/* ******** IMAGE PROCESSING ************* */ + +/* used by sequencer */ +void converttopremul(struct ImBuf *ibuf) { - unsigned int a; + int x, y, val; + char *cp; + + if(ibuf==0) return; + if(ibuf->depth==24) { /* put alpha at 255 */ + + cp= (char *)(ibuf->rect); + for(y=0; yy; y++) { + for(x=0; xx; x++, cp+=4) { + cp[3]= 255; + } + } + return; + } - if(ima->ibuf) { - if (ima->ibuf->userdata) { - MEM_freeN(ima->ibuf->userdata); - ima->ibuf->userdata = NULL; + cp= (char *)(ibuf->rect); + for(y=0; yy; y++) { + for(x=0; xx; x++, cp+=4) { + if(cp[3]==0) { + cp[0]= cp[1]= cp[2]= 0; + } + else if(cp[3]!=255) { + val= cp[3]; + cp[0]= (cp[0]*val)>>8; + cp[1]= (cp[1]*val)>>8; + cp[2]= (cp[2]*val)>>8; + } } - IMB_freeImBuf(ima->ibuf); - ima->ibuf= NULL; } - if(ima->anim) IMB_free_anim(ima->anim); - ima->anim= NULL; +} + +static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ +{ + struct ImBuf * tbuf1, * tbuf2; - for(a=0; amipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - ima->mipmap[a]= NULL; + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* make copies */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + + ibuf->x *= 2; + + IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); + IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + + ibuf->x /= 2; + IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y); + IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); } + ibuf->y /= 2; +} + +static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ +{ + struct ImBuf * tbuf1, * tbuf2; - free_realtime_image(ima); + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* make copies */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + + ibuf->x *= 2; + + IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); + IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + + ibuf->x /= 2; + IMB_rectcpy(ibuf, tbuf2, 0, 0, 0, 0, tbuf2->x, tbuf2->y); + IMB_rectcpy(ibuf, tbuf1, 0, tbuf2->y, 0, 0, tbuf1->x, tbuf1->y); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); + } + ibuf->y /= 2; +} + +void image_de_interlace(Image *ima, int odd) +{ + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf) { + if(odd) + de_interlace_st(ibuf); + else + de_interlace_ng(ibuf); + } } -void free_image_preview(struct Image *ima) +/* ***************** ALLOC & FREE, DATA MANAGING *************** */ + +static void image_free_buffers(Image *ima) { + ImBuf *ibuf; + + while((ibuf = ima->ibufs.first)) { + BLI_remlink(&ima->ibufs, ibuf); + + if (ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata = NULL; + } + IMB_freeImBuf(ibuf); + } + + if(ima->anim) IMB_free_anim(ima->anim); + ima->anim= NULL; + if (ima->preview) { MEM_freeN(ima->preview->rect); MEM_freeN(ima->preview); - ima->preview = 0; + ima->preview = NULL; } + + if(ima->rr) { + RE_FreeRenderResult(ima->rr); + ima->rr= NULL; + } + + free_realtime_image(ima); + + ima->ok= IMA_OK; } +/* called by library too, do not free ima itself */ void free_image(Image *ima) { - free_image_buffers(ima); + image_free_buffers(ima); if (ima->packedfile) { freePackedFile(ima->packedfile); ima->packedfile = NULL; } - free_image_preview(ima); BKE_icon_delete(&ima->id); ima->id.icon_id = 0; } +/* only image block itself */ +static Image *image_alloc(const char *name, short source, short type) +{ + Image *ima; + + ima= alloc_libblock(&G.main->image, ID_IM, name); + if(ima) { + ima->ok= IMA_OK; + + ima->xrep= ima->yrep= 1; + ima->gen_x= 256; ima->gen_y= 256; + ima->gen_type= 1; /* no defines yet? */ + + ima->source= source; + ima->type= type; + } + return ima; +} + +/* get the ibuf from an image cache, local use here only */ +static ImBuf *image_get_ibuf(Image *ima, int index, int frame) +{ + if(index==IMA_NO_INDEX) + return ima->ibufs.first; + else { + ImBuf *ibuf; + + index= IMA_MAKE_INDEX(frame, index); + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) + if(ibuf->index==index) + return ibuf; + return NULL; + } +} + +/* no ima->ibuf anymore, but listbase */ +static void image_remove_ibuf(Image *ima, ImBuf *ibuf) +{ + if(ibuf) { + BLI_remlink(&ima->ibufs, ibuf); + IMB_freeImBuf(ibuf); + } +} + + +/* no ima->ibuf anymore, but listbase */ +static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) +{ + if(ibuf) { + ImBuf *link; + + if(index!=IMA_NO_INDEX) + index= IMA_MAKE_INDEX(frame, index); + + /* insert based on index */ + for(link= ima->ibufs.first; link; link= link->next) + if(link->index>=index) + break; + /* now we don't want copies? */ + if(link && ibuf->index==link->index) { + ImBuf *prev= ibuf->prev; + image_remove_ibuf(ima, link); + link= prev; + } + + /* this function accepts link==NULL */ + BLI_insertlinkbefore(&ima->ibufs, link, ibuf); + + ibuf->index= index; + } + +} -Image *add_image(char *name) +/* checks if image was already loaded, then returns same image */ +/* otherwise creates new. */ +/* does not load ibuf itself */ +Image *BKE_add_image_file(const char *name) { Image *ima; int file, len; - char *libname, str[256], strtest[256]; + const char *libname; + char str[FILE_MAX], strtest[FILE_MAX]; - strcpy(str, name); + BLI_strncpy(str, name, sizeof(str)); BLI_convertstringcode(str, G.sce, G.scene->r.cfra); file= open(str, O_BINARY|O_RDONLY); @@ -133,135 +323,188 @@ Image *add_image(char *name) close(file); /* first search an identical image */ - ima= G.main->image.first; - while(ima) { - strcpy(strtest, ima->name); - BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); - if( strcmp(strtest, str)==0 ) { - if(ima->anim==0 || ima->id.us==0) { - strcpy(ima->name, name); /* for stringcode */ - ima->id.us++; /* officially should not, it doesn't link here! */ - ima->ok= 1; - return ima; + for(ima= G.main->image.first; ima; ima= ima->id.next) { + if(ima->source!=IMA_SRC_VIEWER) { + BLI_strncpy(strtest, ima->name, sizeof(ima->name)); + BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); + + if( strcmp(strtest, str)==0 ) { + if(ima->anim==NULL || ima->id.us==0) { + BLI_strncpy(ima->name, name, sizeof(ima->name)); /* for stringcode */ + ima->id.us++; /* officially should not, it doesn't link here! */ + if(ima->ok==0) + ima->ok= IMA_OK; + /* RETURN! */ + return ima; + } } } - ima= ima->id.next; } - + /* add new image */ + + /* create a short library name */ len= strlen(name); while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--; libname= name+len; - ima= alloc_libblock(&G.main->image, ID_IM, libname); - strcpy(ima->name, name); - ima->ok= 1; + ima= image_alloc(libname, IMA_SRC_FILE, IMA_TYPE_IMAGE); + BLI_strncpy(ima->name, name, sizeof(ima->name)); - ima->xrep= ima->yrep= 1; + /* do a wild guess! */ + if(BLI_testextensie(name, ".avi") || BLI_testextensie(name, ".mov") + || BLI_testextensie(name, ".mpg") || BLI_testextensie(name, ".mp4")) + ima->source= IMA_SRC_MOVIE; return ima; } -Image *new_image(int width, int height, char *name, short uvtestgrid) +static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid) { - Image *ima; - - ima = alloc_libblock(&G.main->image, ID_IM, name); + ImBuf *ibuf; + float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b; + unsigned char *rect; + int x, y; + int checkerwidth=21, dark=1; - if (ima) - { - ImBuf *ibuf; - unsigned char *rect; - int x, y; - int checkerwidth=21, dark=1; - float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b; - - strcpy(ima->name, "Untitled"); - - ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); - strcpy(ibuf->name, "Untitled"); - ima->ibuf= ibuf; - ibuf->userflags |= IB_BITMAPDIRTY; - - rect= (unsigned char*)ibuf->rect; + ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); + strcpy(ibuf->name, "Untitled"); + ibuf->userflags |= IB_BITMAPDIRTY; + + rect= (unsigned char*)ibuf->rect; + + if (uvtestgrid) { + /* these two passes could be combined into one, but it's more readable and + * easy to tweak like this, speed isn't really that much of an issue in this situation... */ - if (uvtestgrid) { - /* these two passes could be combined into one, but it's more readable and - * easy to tweak like this, speed isn't really that much of an issue in this situation... */ - - /* checkers */ - for(y=0; yy; y++) { - dark = pow(-1, floor(y / checkerwidth)); + /* checkers */ + for(y=0; yy; y++) { + dark = pow(-1, floor(y / checkerwidth)); + + for(x=0; xx; x++, rect+=4) { + if (x % checkerwidth == 0) dark *= -1; - for(x=0; xx; x++, rect+=4) { - if (x % checkerwidth == 0) dark *= -1; - - if (dark > 0) { - rect[0] = rect[1] = rect[2] = 64; - rect[3] = 255; - } else { - rect[0] = rect[1] = rect[2] = 150; - rect[3] = 255; - } + if (dark > 0) { + rect[0] = rect[1] = rect[2] = 64; + rect[3] = 255; + } else { + rect[0] = rect[1] = rect[2] = 150; + rect[3] = 255; } } - - /* 2nd pass, coloured + */ - rect= (unsigned char*)ibuf->rect; + } + + /* 2nd pass, coloured + */ + rect= (unsigned char*)ibuf->rect; + + for(y=0; yy; y++) { + hoffs = 0.125 * floor(y / checkerwidth); - for(y=0; yy; y++) { - hoffs = 0.125 * floor(y / checkerwidth); + for(x=0; xx; x++, rect+=4) { + h = 0.125 * floor(x / checkerwidth); - for(x=0; xx; x++, rect+=4) { - h = 0.125 * floor(x / checkerwidth); - - if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) && - (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) { + if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) && + (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) { + + if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) || + (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) { - if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) || - (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) { + hue = fmod(fabs(h-hoffs), 1.0); + hsv_to_rgb(hue, s, v, &r, &g, &b); - hue = fmod(fabs(h-hoffs), 1.0); - hsv_to_rgb(hue, s, v, &r, &g, &b); - - rect[0]= (char)(r * 255.0); - rect[1]= (char)(g * 255.0); - rect[2]= (char)(b * 255.0); - rect[3]= 255; - } + rect[0]= (char)(r * 255.0); + rect[1]= (char)(g * 255.0); + rect[2]= (char)(b * 255.0); + rect[3]= 255; } - } + } - } else { /* blank image */ - for(y=0; yy; y++) { - for(x=0; xx; x++, rect+=4) { - rect[0]= rect[1]= rect[2]= 0; - rect[3]= 255; - } + } + } else { /* blank image */ + for(y=0; yy; y++) { + for(x=0; xx; x++, rect+=4) { + rect[0]= rect[1]= rect[2]= 0; + rect[3]= 255; } } + } + return ibuf; +} - ima->ok= 1; - ima->xrep= ima->yrep= 1; +/* adds new image block, creates ImBuf and initializes color */ +Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid) +{ + Image *ima; + + /* on save, type is changed to FILE in editsima.c */ + ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); + + if (ima) { + ImBuf *ibuf; + + BLI_strncpy(ima->name, name, FILE_MAX); + ima->gen_x= width; + ima->gen_y= height; + ima->gen_type= uvtestgrid; + + ibuf= add_ibuf_size(width, height, name, uvtestgrid); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + + ima->ok= IMA_OK_LOADED; } return ima; } +/* packs rect from memory as PNG */ +void BKE_image_memorypack(Image *ima) +{ + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + + if(ibuf==NULL) + return; + if (ima->packedfile) { + freePackedFile(ima->packedfile); + ima->packedfile = NULL; + } + + ibuf->ftype= PNG; + ibuf->depth= 32; + + IMB_saveiff(ibuf, ibuf->name, IB_rect | IB_mem); + if(ibuf->encodedbuffer==NULL) { + printf("memory save for pack error\n"); + } + else { + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); + + pf->data = ibuf->encodedbuffer; + pf->size = ibuf->encodedsize; + ima->packedfile= pf; + ibuf->encodedbuffer= NULL; + ibuf->encodedsize= 0; + ibuf->userflags &= ~IB_BITMAPDIRTY; + + if(ima->source==IMA_SRC_GENERATED) + ima->source= IMA_SRC_FILE; + } +} + void tag_image_time(Image *ima) { if (ima) ima->lastused = (int)PIL_check_seconds_timer(); } -void tag_all_images_time() { +void tag_all_images_time() +{ Image *ima; int ctime = (int)PIL_check_seconds_timer(); ima= G.main->image.first; while(ima) { - if(ima->bindcode || ima->repbind || ima->ibuf) { + if(ima->bindcode || ima->repbind || ima->ibufs.first) { ima->lastused = ctime; } } @@ -294,29 +537,15 @@ void free_old_images() ima->lastused = ctime; } /* Otherwise, just kill the buffers */ - else if (ima->ibuf) { - free_image_buffers(ima); + else if (ima->ibufs.first) { + image_free_buffers(ima); } } ima = ima->id.next; } } -void free_unused_animimages() -{ - Image *ima, *nima; - - ima= G.main->image.first; - while(ima) { - nima= ima->id.next; - if(ima->id.us==0) { - if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima); - } - ima= nima; - } -} - -void free_all_imagetextures(void) +void BKE_image_free_all_textures(void) { Tex *tex; Image *ima; @@ -330,19 +559,116 @@ void free_all_imagetextures(void) tex->ima->id.flag |= LIB_DOIT; for(ima= G.main->image.first; ima; ima= ima->id.next) { - if(ima->ibuf && (ima->id.flag & LIB_DOIT)) { - if(ima->mipmap[0]) - totsize+= 1.33*ima->ibuf->x*ima->ibuf->y*4; - else - totsize+= ima->ibuf->x*ima->ibuf->y*4; - free_image_buffers(ima); + if(ima->ibufs.first && (ima->id.flag & LIB_DOIT)) { + ImBuf *ibuf; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { + if(ibuf->mipmap[0]) + totsize+= 1.33*ibuf->x*ibuf->y*4; + else + totsize+= ibuf->x*ibuf->y*4; + } + image_free_buffers(ima); } } - printf("freed total %d MB\n", totsize/(1024*1024)); + /* printf("freed total %d MB\n", totsize/(1024*1024)); */ } +/* except_frame is weak, only works for seqs without offset... */ +void BKE_image_free_anim_ibufs(Image *ima, int except_frame) +{ + ImBuf *ibuf, *nbuf; + + for(ibuf= ima->ibufs.first; ibuf; ibuf= nbuf) { + nbuf= ibuf->next; + if(ibuf->userflags & IB_BITMAPDIRTY) + continue; + if(ibuf->index==IMA_NO_INDEX) + continue; + if(except_frame!=IMA_INDEX_FRAME(ibuf->index)) { + BLI_remlink(&ima->ibufs, ibuf); + + if (ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata = NULL; + } + IMB_freeImBuf(ibuf); + } + } +} + +void BKE_image_all_free_anim_ibufs(int cfra) +{ + Image *ima; + + for(ima= G.main->image.first; ima; ima= ima->id.next) + if(ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) + BKE_image_free_anim_ibufs(ima, cfra); +} + + /* *********** READ AND WRITE ************** */ +int BKE_imtype_to_ftype(int imtype) +{ + if(imtype==0) + return TGA; + else if(imtype== R_IRIS) + return IMAGIC; + else if (imtype==R_RADHDR) + return RADHDR; + else if (imtype==R_PNG) + return PNG; + else if (imtype==R_BMP) + return BMP; + else if (imtype==R_TIFF) + return TIF; + else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) + return OPENEXR; + else if (imtype==R_CINEON) + return CINEON; + else if (imtype==R_DPX) + return DPX; + else if (imtype==R_TARGA) + return TGA; + else if(imtype==R_RAWTGA) + return RAWTGA; + else if(imtype==R_HAMX) + return AN_hamx; + else + return JPG|90; +} + +int BKE_ftype_to_imtype(int ftype) +{ + if(ftype==0) + return TGA; + else if(ftype == IMAGIC) + return R_IRIS; + else if (ftype & RADHDR) + return R_RADHDR; + else if (ftype & PNG) + return R_PNG; + else if (ftype & BMP) + return R_BMP; + else if (ftype & TIF) + return R_TIFF; + else if (ftype & OPENEXR) + return R_OPENEXR; + else if (ftype & CINEON) + return R_CINEON; + else if (ftype & DPX) + return R_DPX; + else if (ftype & TGA) + return R_TARGA; + else if(ftype & RAWTGA) + return R_RAWTGA; + else if(ftype == AN_hamx) + return R_HAMX; + else + return R_JPEG90; +} + + int BKE_imtype_is_movie(int imtype) { switch(imtype) { @@ -395,7 +721,7 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".tif"; } #ifdef WITH_OPENEXR - else if(imtype==R_OPENEXR) { + else if( ELEM(imtype, R_OPENEXR, R_MULTILAYER)) { if(!BLI_testextensie(string, ".exr")) extension= ".exr"; } @@ -437,7 +763,7 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali ibuf->ftype= TIF; } #ifdef WITH_OPENEXR - else if (imtype==R_OPENEXR) { + else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) { ibuf->ftype= OPENEXR; if(subimtype & R_OPENEXR_HALF) ibuf->ftype |= OPENEXR_HALF; @@ -488,7 +814,7 @@ void BKE_makepicstring(char *string, char *base, int frame, int imtype) if (string==NULL) return; - BLI_strncpy(string, base, FILE_MAXDIR + FILE_MAXFILE - 10); /* weak assumption */ + BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ BLI_convertstringcode(string, G.sce, frame); len= strlen(string); @@ -506,43 +832,7 @@ void BKE_makepicstring(char *string, char *base, int frame, int imtype) } -/* ******** IMAGE WRAPPING INIT ************* */ - -/* used by sequencer, texture */ -void converttopremul(struct ImBuf *ibuf) -{ - int x, y, val; - char *cp; - - if(ibuf==0) return; - if(ibuf->depth==24) { /* put alpha at 255 */ - - cp= (char *)(ibuf->rect); - for(y=0; yy; y++) { - for(x=0; xx; x++, cp+=4) { - cp[3]= 255; - } - } - return; - } - - cp= (char *)(ibuf->rect); - for(y=0; yy; y++) { - for(x=0; xx; x++, cp+=4) { - if(cp[3]==0) { - cp[0]= cp[1]= cp[2]= 0; - } - else if(cp[3]!=255) { - val= cp[3]; - cp[0]= (cp[0]*val)>>8; - cp[1]= (cp[1]*val)>>8; - cp[2]= (cp[2]*val)>>8; - } - } - } -} - -/* used by sequencer, texture */ +/* used by sequencer too */ struct anim *openanim(char *name, int flags) { struct anim *anim; @@ -562,198 +852,656 @@ struct anim *openanim(char *name, int flags) return(anim); } +/* ************************* New Image API *************** */ + + +/* Notes about Image storage +- packedfile + -> written in .blend +- filename + -> written in .blend +- movie + -> comes from packedfile or filename +- renderresult + -> comes from packedfile or filename +- listbase + -> ibufs from exrhandle +- flipbook array + -> ibufs come from movie, temporary renderresult or sequence +- ibuf + -> comes from packedfile or filename or generated -/* -load_image handles reading the image from disk or from the packedfile. */ -void load_image(Image * ima, int flags, char *relabase, int framenum) -{ - char name[FILE_MAXDIR + FILE_MAXFILE]; - if(ima->id.lib) relabase= ima->id.lib->filename; +/* forces existance of 1 Image for renderout or nodes, returns Image */ +/* name is only for default, when making new one */ +Image *BKE_image_verify_viewer(int type, const char *name) +{ + Image *ima; - if (ima->ibuf == NULL) { - - // is there a PackedFile with this image ?; - if (ima->packedfile) { - ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags); - } else { - strcpy(name, ima->name); - BLI_convertstringcode(name, relabase, framenum); + for(ima=G.main->image.first; ima; ima= ima->id.next) + if(ima->source==IMA_SRC_VIEWER) + if(ima->type==type) + break; + + if(ima==NULL) + ima= image_alloc(name, IMA_SRC_VIEWER, type); + + /* happens on reload, imagewindow cannot be image user when hidden*/ + if(ima->id.us==0) + id_us_plus(&ima->id); - ima->ibuf = IMB_loadiffname(name , flags); - } - // check if the image is a font image... - // printf("Checking for font\n"); + return ima; +} - if (ima->ibuf) { - detectBitmapFont(ima->ibuf); - /* preview is NULL when it has never been used as an icon before */ - if(G.background==0 && ima->preview==NULL) - BKE_icon_changed(BKE_icon_getid(&ima->id)); +void BKE_image_assign_ibuf(Image *ima, ImBuf *ibuf) +{ + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); +} +void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) +{ + if(ima==NULL) + return; + + switch(signal) { + case IMA_SIGNAL_FREE: + image_free_buffers(ima); + if(iuser) + iuser->ok= 1; + break; + case IMA_SIGNAL_SRC_CHANGE: + if(ima->type==IMA_TYPE_MULTILAYER) + image_free_buffers(ima); + else if(ima->source==IMA_SRC_GENERATED) { + if(ima->gen_x==0 || ima->gen_y==0) { + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + if(ibuf) { + ima->gen_x= ibuf->x; + ima->gen_y= ibuf->y; + } + } + } + ima->ok= 1; + if(iuser) + iuser->ok= 1; + break; + + case IMA_SIGNAL_RELOAD: + /* try to repack file */ + if(ima->packedfile) { + PackedFile *pf; + pf = newPackedFile(ima->name); + if (pf) { + freePackedFile(ima->packedfile); + ima->packedfile = pf; + image_free_buffers(ima); + } else { + printf("ERROR: Image not available. Keeping packed image\n"); + } } + else + image_free_buffers(ima); + + if(iuser) + iuser->ok= 1; + + break; + case IMA_SIGNAL_USER_NEW_IMAGE: + if(iuser) { + iuser->ok= 1; + if(ima->source==IMA_SRC_FILE || ima->source==IMA_SRC_SEQUENCE) { + if(ima->type==IMA_TYPE_MULTILAYER) { + iuser->multi_index= 0; + iuser->layer= iuser->pass= 0; + } + } + } + break; } } - -static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ +/* if layer or pass changes, we need an index for the imbufs list */ +/* note it is called for rendered results, but it doesnt use the index! */ +/* and because rendered results use fake layer/passes, don't correct for wrong indices here */ +RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) { - struct ImBuf * tbuf1, * tbuf2; + RenderLayer *rl; + RenderPass *rpass= NULL; - if (ibuf == 0) return; - if (ibuf->flags & IB_fields) return; - ibuf->flags |= IB_fields; + if(rr==NULL) + return NULL; - if (ibuf->rect) { - /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + if(iuser) { + short index= 0, rl_index= 0, rp_index; - ibuf->x *= 2; + for(rl= rr->layers.first; rl; rl= rl->next, rl_index++) { + rp_index= 0; + for(rpass= rl->passes.first; rpass; rpass= rpass->next, index++, rp_index++) + if(iuser->layer==rl_index && iuser->pass==rp_index) + break; + if(rpass) + break; + } - IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); - IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + if(rpass) + iuser->multi_index= index; + else + iuser->multi_index= 0; + } + if(rpass==NULL) { + rl= rr->layers.first; + if(rl) + rpass= rl->passes.first; + } + + return rpass; +} + +RenderResult *BKE_image_get_renderresult(Image *ima) +{ + if(ima->rr) + return ima->rr; + if(ima->type==IMA_TYPE_R_RESULT) + return RE_GetResult(RE_GetRender(G.scene->id.name)); + return NULL; +} + +/* after imbuf load, openexr type can return with a exrhandle open */ +/* in that case we have to build a render-result */ +static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) +{ + + ima->rr= RE_MultilayerConvert(ibuf->userdata, ibuf->x, ibuf->y); + IMB_exr_close(ibuf->userdata); + ibuf->userdata= NULL; + if(ima->rr) + ima->rr->framenr= framenr; +} + +/* common stuff to do with images after loading */ +static void image_initialize_after_load(Image *ima, ImBuf *ibuf) +{ + + + /* preview is NULL when it has never been used as an icon before */ + if(G.background==0 && ima->preview==NULL) + BKE_icon_changed(BKE_icon_getid(&ima->id)); + + /* stringcodes also in ibuf, ibuf->name is used to retrieve original (buttons) */ + BLI_strncpy(ibuf->name, ima->name, FILE_MAX); + + /* fields */ + if (ima->flag & IMA_FIELDS) { + if(ima->flag & IMA_STD_FIELD) de_interlace_st(ibuf); + else de_interlace_ng(ibuf); + } + /* timer */ + ima->lastused = clock() / CLOCKS_PER_SEC; + + ima->ok= IMA_OK_LOADED; + +} + +static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf; + unsigned short numlen; + char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX]; + + ima->lastframe= frame; + + BLI_stringdec(ima->name, head, tail, &numlen); + BLI_stringenc(ima->name, head, tail, numlen, frame); + BLI_strncpy(name, ima->name, sizeof(name)); + + if(ima->id.lib) + BLI_convertstringcode(name, ima->id.lib->filename, frame); + else + BLI_convertstringcode(name, G.sce, frame); + + /* read ibuf */ + ibuf = IMB_loadiffname(name, IB_rect|IB_multilayer); + printf("loaded %s\n", name); + + if (ibuf) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + if (ibuf->ftype==OPENEXR && ibuf->userdata) { + image_create_multilayer(ima, ibuf, frame); + ima->type= IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf= NULL; + } + else { + image_assign_ibuf(ima, ibuf, 0, frame); + image_initialize_after_load(ima, ibuf); + } + } + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; +} + +static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf= NULL; + + /* either we load from RenderResult, or we have to load a new one */ + + /* check for new RenderResult */ + if(ima->rr==NULL || frame!=ima->rr->framenr) { + /* copy to survive not found multilayer image */ + RenderResult *oldrr= ima->rr; + + ima->rr= NULL; + ibuf = image_load_sequence_file(ima, iuser, frame); - ibuf->x /= 2; - IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y); - IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y); + if(ibuf) { /* actually an error */ + ima->type= IMA_TYPE_IMAGE; + printf("error, multi is normal image\n"); + } + // printf("loaded new result %p\n", ima->rr); + /* free result if new one found */ + if(ima->rr) { + // if(oldrr) printf("freed previous result %p\n", oldrr); + if(oldrr) RE_FreeRenderResult(oldrr); + } + else + ima->rr= oldrr; + + } + if(ima->rr) { + RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser); - IMB_freeImBuf(tbuf1); - IMB_freeImBuf(tbuf2); + if(rpass) { + // printf("load from pass %s\n", rpass->name); + /* since we free render results, we copy the rect */ + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + ibuf->rect_float= MEM_dupallocN(rpass->rect); + ibuf->flags |= IB_rectfloat; + ibuf->mall= IB_rectfloat; + ibuf->channels= rpass->channels; + + image_assign_ibuf(ima, ibuf, iuser->multi_index, frame); + image_initialize_after_load(ima, ibuf); + + } + // else printf("pass not found\n"); } - ibuf->y /= 2; + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ + +static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) { - struct ImBuf * tbuf1, * tbuf2; + struct ImBuf *ibuf= NULL; - if (ibuf == 0) return; - if (ibuf->flags & IB_fields) return; - ibuf->flags |= IB_fields; + ima->lastframe= frame; - if (ibuf->rect) { - /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + if(ima->anim==NULL) { + char str[FILE_MAX]; - ibuf->x *= 2; + BLI_strncpy(str, ima->name, FILE_MAX); + if(ima->id.lib) + BLI_convertstringcode(str, ima->id.lib->filename, 0); + else + BLI_convertstringcode(str, G.sce, 0); - IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); - IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + ima->anim = openanim(str, IB_cmap | IB_rect); - ibuf->x /= 2; - IMB_rectcpy(ibuf, tbuf2, 0, 0, 0, 0, tbuf2->x, tbuf2->y); - IMB_rectcpy(ibuf, tbuf1, 0, tbuf2->y, 0, 0, tbuf1->x, tbuf1->y); + /* let's initialize this user */ + if(ima->anim && iuser && iuser->frames==0) + iuser->frames= IMB_anim_get_duration(ima->anim); + } + + if(ima->anim) { + int dur = IMB_anim_get_duration(ima->anim); + int fra= frame-1; - IMB_freeImBuf(tbuf1); - IMB_freeImBuf(tbuf2); + if(fra<0) fra = 0; + if(fra>(dur-1)) fra= dur-1; + ibuf = IMB_anim_absolute(ima->anim, fra); + + if(ibuf) { + image_assign_ibuf(ima, ibuf, 0, frame); + image_initialize_after_load(ima, ibuf); + } + else + ima->ok= 0; } - ibuf->y /= 2; + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -void image_de_interlace(Image *ima, int odd) +/* cfra used for # code, Image can only have this # for all its users */ +static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { - if(odd) - de_interlace_st(ima->ibuf); + struct ImBuf *ibuf; + char str[FILE_MAX]; + + /* always ensure clean ima */ + image_free_buffers(ima); + + /* is there a PackedFile with this image ? */ + if (ima->packedfile) { + ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, IB_rect|IB_multilayer); + } + else { + + /* get the right string */ + BLI_strncpy(str, ima->name, sizeof(str)); + if(ima->id.lib) + BLI_convertstringcode(str, ima->id.lib->filename, cfra); + else + BLI_convertstringcode(str, G.sce, cfra); + + /* read ibuf */ + ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer); + } + + if (ibuf) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + if (ibuf->ftype==OPENEXR && ibuf->userdata) { + image_create_multilayer(ima, ibuf, cfra); + ima->type= IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf= NULL; + } + else { + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + image_initialize_after_load(ima, ibuf); + + /* check if the image is a font image... */ + detectBitmapFont(ibuf); + + /* make packed file for autopack */ + if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) + ima->packedfile = newPackedFile(str); + } + } else - de_interlace_ng(ima->ibuf); + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -void ima_ibuf_is_nul(Tex *tex, Image *ima) +static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) { - void (*de_interlacefunc)(struct ImBuf *ibuf); - unsigned int a; - int fra, dur; - char str[FILE_MAXDIR+FILE_MAXFILE], *cp; + ImBuf *ibuf= NULL; - if(ima==0) return; + if(ima->rr==NULL) { + ibuf = image_load_image_file(ima, iuser, 0); + if(ibuf) { /* actually an error */ + ima->type= IMA_TYPE_IMAGE; + return ibuf; + } + } + if(ima->rr) { + RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser); + + if(rpass) { + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + + image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0); + image_initialize_after_load(ima, ibuf); + + ibuf->rect_float= rpass->rect; + ibuf->flags |= IB_rectfloat; + ibuf->channels= rpass->channels; + } + } - strcpy(str, ima->name); - if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, G.scene->r.cfra); - else - BLI_convertstringcode(str, G.sce, G.scene->r.cfra); + if(ibuf==NULL) + ima->ok= 0; + if(iuser) + iuser->ok= ima->ok; - if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st; - else de_interlacefunc= de_interlace_ng; + return ibuf; +} + + +/* showing RGBA result itself (from compo/sequence) or + like exr, using layers etc */ +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) +{ + RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); - if(tex->imaflag & TEX_ANIM5) { + if(rr && iuser) { + RenderResult rres; + float *rectf; + unsigned int *rect; + int channels= 4, layer= iuser->layer; - if(ima->anim==NULL) ima->anim = openanim(str, IB_cmap | IB_rect); - if (ima->anim) { - dur = IMB_anim_get_duration(ima->anim); - - fra= ima->lastframe-1; - - if(fra<0) fra = 0; - if(fra>(dur-1)) fra= dur-1; - ima->ibuf = IMB_anim_absolute(ima->anim, fra); - - /* patch for textbutton with name ima (B_NAMEIMA) */ - if(ima->ibuf) { - strcpy(ima->ibuf->name, ima->name); - if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); + /* this gives active layer, composite or seqence result */ + RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + rect= rres.rect32; + rectf= rres.rectf; + + /* get compo/seq result by default */ + if(rr->rectf && layer==0); + else if(rr->layers.first) { + RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer-(rr->rectf?1:0)); + if(rl) { + /* there's no combined pass, is in renderlayer itself */ + if(iuser->pass==0) { + rectf= rl->rectf; + } + else { + RenderPass *rpass= BLI_findlink(&rl->passes, iuser->pass-1); + if(rpass) { + channels= rpass->channels; + rectf= rpass->rect; + } + } } } - } else { - // create a packedfile for this image when autopack is on - // for performance (IMB_loadiffname uses mmap) we don't do this by default - if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) { - ima->packedfile = newPackedFile(str); + if(rectf || rect) { + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + + /* make ibuf if needed, and initialize it */ + if(ibuf==NULL) { + ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, 0, 0); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } + ibuf->x= rr->rectx; + ibuf->y= rr->recty; + + if(ibuf->rect_float!=rectf || rect) /* ensure correct redraw */ + imb_freerectImBuf(ibuf); + if(rect) + ibuf->rect= rect; + + ibuf->rect_float= rectf; + ibuf->flags |= IB_rectfloat; + ibuf->channels= channels; + + ima->ok= IMA_OK_LOADED; + return ibuf; } - - load_image(ima, IB_rect, G.sce, G.scene->r.cfra); - - if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); } - if(ima->ibuf) { + return NULL; +} + +/* Checks optional ImageUser and verifies/creates ImBuf. */ +/* returns ibuf */ +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + ImBuf *ibuf= NULL; + + /* quick reject tests */ + if(ima==NULL) + return NULL; + if(iuser) { + if(iuser->ok==0) + return NULL; + } + else if(ima->ok==0) + return NULL; + + BLI_lock_thread(LOCK_CUSTOM1); + + /* handle image source and types */ + if(ima->source==IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + int frame= iuser?iuser->framenr:ima->lastframe; - /* stringcodes also in ibuf. ibuf->name is used as 'undo' (buttons.c) */ - strcpy(ima->ibuf->name, ima->name); + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) + ibuf= image_load_movie_file(ima, iuser, frame); + } + else if(ima->source==IMA_SRC_SEQUENCE) { - if(ima->ibuf->cmap) { + if(ima->type==IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + int frame= iuser?iuser->framenr:ima->lastframe; - if(tex->imaflag & TEX_ANIM5) { - - if(tex->imaflag & TEX_MORKPATCH) { - /**** PATCH TO SET COLOR 2 RIGHT (neogeo..) */ - if(ima->ibuf->maxcol > 4) { - cp= (char *)(ima->ibuf->cmap+2); - cp[0]= 0x80; - } - } - - IMB_applycmap(ima->ibuf); - IMB_convert_rgba_to_abgr(ima->ibuf); - - } + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) + ibuf= image_load_sequence_file(ima, iuser, frame); + else + BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); + } + /* no else; on load the ima type can change */ + if(ima->type==IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + int frame= iuser?iuser->framenr:ima->lastframe; + int index= iuser?iuser->multi_index:IMA_NO_INDEX; - converttopremul(ima->ibuf); + ibuf= image_get_ibuf(ima, index, frame); + if(G.rt) printf("seq multi fra %d id %d ibuf %p %s\n", frame, index, ibuf, ima->id.name); + if(ibuf==NULL) + ibuf= image_load_sequence_multilayer(ima, iuser, frame); + else + BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); + } + + } + else if(ima->source==IMA_SRC_FILE) { + + if(ima->type==IMA_TYPE_IMAGE) { + ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + if(ibuf==NULL) + ibuf= image_load_image_file(ima, iuser, G.scene->r.cfra); /* cfra only for '#', this global is OK */ } + /* no else; on load the ima type can change */ + if(ima->type==IMA_TYPE_MULTILAYER) { + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf= image_get_ibuf(ima, iuser?iuser->multi_index:IMA_NO_INDEX, 0); + if(ibuf==NULL) + ibuf= image_get_ibuf_multilayer(ima, iuser); + } + + } + else if(ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); - if(tex->imaflag & TEX_ANTISCALE) { - IMB_clever_double(ima->ibuf); - IMB_antialias(ima->ibuf); + if(ibuf==NULL) { + if(ima->type==IMA_TYPE_VERSE) { + /* todo */ + } + else { /* always fall back to IMA_TYPE_UV_TEST */ + /* UV testgrid or black or solid etc */ + if(ima->gen_x==0) ima->gen_x= 256; + if(ima->gen_y==0) ima->gen_y= 256; + ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_type); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } } - else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf); } - - if(ima->ibuf) - ima->lastused = clock() / CLOCKS_PER_SEC; - else - ima->ok= 0; - - for(a=0; amipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - ima->mipmap[a]= 0; + else if(ima->source == IMA_SRC_VIEWER) { + if(ima->type==IMA_TYPE_R_RESULT) { + /* always verify entirely */ + ibuf= image_get_render_result(ima, iuser); + } + else if(ima->type==IMA_TYPE_COMPOSITE) { + int frame= iuser?iuser->framenr:0; + + /* Composite Viewer, all handled in compositor */ + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) { + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, 0, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } + } } + if(G.rendering==0) + tag_image_time(ima); + + BLI_unlock_thread(LOCK_CUSTOM1); + + return ibuf; } +void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) +{ + int imanr, len; + + /* here (+fie_ima/2-1) makes sure that division happens correctly */ + len= (iuser->fie_ima*iuser->frames)/2; + + if(len==0) { + iuser->framenr= 0; + } + else { + cfra= cfra - iuser->sfra+1; + + /* cyclic */ + if(iuser->cycl) { + cfra= ( (cfra) % len ); + if(cfra < 0) cfra+= len; + if(cfra==0) cfra= len; + } + + if(cfra<1) cfra= 1; + else if(cfra>len) cfra= len; + + /* convert current frame to current field */ + cfra= 2*(cfra); + if(fieldnr) cfra++; + + /* transform to images space */ + imanr= (cfra+iuser->fie_ima-2)/iuser->fie_ima; + if(imanr>iuser->frames) imanr= iuser->frames; + imanr+= iuser->offset; + + if(iuser->cycl) { + imanr= ( (imanr) % len ); + while(imanr < 0) imanr+= len; + if(imanr==0) imanr= len; + } + + /* allows image users to handle redraws */ + if(iuser->flag & IMA_ANIM_ALWAYS) + if(imanr!=iuser->framenr) + iuser->flag |= IMA_ANIM_REFRESHED; + + iuser->framenr= imanr; + if(iuser->ok==0) iuser->ok= 1; + } +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index b5680f98940..ba19ba5d8b2 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -569,7 +569,9 @@ static void get_flags_for_id(ID *id, char *buf) sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' '); } -static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr) +#define IDPUP_NO_VIEWER 1 + +static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int hideflag) { int i, nids= BLI_countlist(lb); @@ -588,6 +590,10 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.') continue; + if (hideflag & IDPUP_NO_VIEWER) + if (GS(id->name)==ID_IM) + if ( ((Image *)id)->source==IMA_SRC_VIEWER ) + continue; get_flags_for_id(id, buf); @@ -681,12 +687,35 @@ void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, BLI_dynstr_append(pupds, "|"); } - IDnames_to_dyn_pupstring(pupds, lb, link, nr); + IDnames_to_dyn_pupstring(pupds, lb, link, nr, 0); *str= BLI_dynstr_get_cstring(pupds); BLI_dynstr_free(pupds); } +/* skips viewer images */ +void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr) +{ + DynStr *pupds= BLI_dynstr_new(); + + if (title) { + BLI_dynstr_append(pupds, title); + BLI_dynstr_append(pupds, "%t|"); + } + + if (extraops) { + BLI_dynstr_append(pupds, extraops); + if (BLI_dynstr_get_len(pupds)) + BLI_dynstr_append(pupds, "|"); + } + + IDnames_to_dyn_pupstring(pupds, lb, link, nr, IDPUP_NO_VIEWER); + + *str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); +} + + // only used by headerbuttons.c void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index bb6439d09fb..d10ff6c6d33 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -31,6 +31,7 @@ #include #include "DNA_ID.h" +#include "DNA_image_types.h" #include "DNA_node_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" @@ -641,7 +642,7 @@ static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **n { bNode *node; bNodeSocket *tsock; - int index; + int index= 0; for(node= ntree->nodes.first; node; node= node->next) { for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) @@ -807,6 +808,13 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup) nbd->samples= 32; nbd->fac= 1.0f; } + else if(ELEM3(type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); + node->storage= iuser; + iuser->sfra= 1; + iuser->fie_ima= 2; + iuser->ok= 1; + } else if(type==CMP_NODE_HUE_SAT) { NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat"); node->storage= nhs; @@ -1488,10 +1496,10 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node) free_compbuf(sock->ns.data); sock->ns.data= NULL; - if(node->preview && node->preview->rect) { - MEM_freeN(node->preview->rect); - node->preview->rect= NULL; - } + //if(node->preview && node->preview->rect) { + // MEM_freeN(node->preview->rect); + // node->preview->rect= NULL; + //} } } @@ -1967,6 +1975,14 @@ static void *exec_composite_node(void *node_v) return 0; } +/* should become a type? these are nodes without input, only giving values */ +static int node_only_value(bNode *node) +{ + if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB)) + return 1; + return 0; +} + /* return total of executable nodes, for timecursor */ /* only compositor uses it */ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) @@ -1991,10 +2007,13 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) node_get_stack(node, thd->stack, nsin, nsout); /* test the outputs */ - for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { - if(nsout[a]->data==NULL && nsout[a]->hasoutput) { - node->need_exec= 1; - break; + /* skip value-only nodes (should be in type!) */ + if(!node_only_value(node)) { + for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { + if(nsout[a]->data==NULL && nsout[a]->hasoutput) { + node->need_exec= 1; + break; + } } } @@ -2008,7 +2027,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) bNodeLink *link= sock->link; /* this is the test for a cyclic case */ if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { - if(nsin[a]->data==NULL || sock->link->fromnode->need_exec) { + if(sock->link->fromnode->need_exec) { node->need_exec= 1; break; } @@ -2030,15 +2049,31 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) } } totnode++; - // printf("node needs exec %s\n", node->name); + /* printf("node needs exec %s\n", node->name); */ /* tag for getExecutableNode() */ node->exec= 0; } - else + else { /* tag for getExecutableNode() */ node->exec= NODE_READY|NODE_FINISHED; + + } } + + /* last step: set the stack values for only-value nodes */ + /* just does all now, compared to a full buffer exec this is nothing */ + if(totnode) { + for(node= ntree->nodes.first; node; node= node->next) { + if(node->need_exec==0 && node_only_value(node)) { + if(node->typeinfo->execfunc) { + node_get_stack(node, thd->stack, nsin, nsout); + node->typeinfo->execfunc(thd->rd, node, nsin, nsout); + } + } + } + } + return totnode; } @@ -2187,8 +2222,6 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeEndExecTree(ntree); - free_unused_animimages(); - } diff --git a/source/blender/blenkernel/intern/node_composite.c b/source/blender/blenkernel/intern/node_composite.c index b35bfba6b3e..9030b072b9d 100644 --- a/source/blender/blenkernel/intern/node_composite.c +++ b/source/blender/blenkernel/intern/node_composite.c @@ -600,10 +600,27 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, /* stack order input sockets: col, alpha, z */ if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ + RenderData *rd= data; Image *ima= (Image *)node->id; + ImBuf *ibuf; CompBuf *cbuf, *tbuf; int rectx, recty; + + BKE_image_user_calc_imanr(node->storage, rd->cfra, 0); + /* always returns for viewer image, but we check nevertheless */ + ibuf= BKE_image_get_ibuf(ima, node->storage); + if(ibuf==NULL) { + printf("node_composit_exec_viewer error\n"); + return; + } + + /* free all in ibuf */ + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + + /* get size */ tbuf= in[0]->data?in[0]->data:(in[1]->data?in[1]->data:in[2]->data); if(tbuf==NULL) { rectx= 320; recty= 256; @@ -613,31 +630,16 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, recty= tbuf->y; } - if(ima->ibuf==NULL) - ima->ibuf= IMB_allocImBuf(rectx, recty, 32, 0, 0); - - /* cleanup of composit image */ - if(ima->ibuf->rect) { - MEM_freeN(ima->ibuf->rect); - ima->ibuf->rect= NULL; - ima->ibuf->mall &= ~IB_rect; - } - if(ima->ibuf->zbuf_float) { - MEM_freeN(ima->ibuf->zbuf_float); - ima->ibuf->zbuf_float= NULL; - ima->ibuf->mall &= ~IB_zbuffloat; - } - if(ima->ibuf->rect_float) - MEM_freeN(ima->ibuf->rect_float); - - ima->ibuf->x= rectx; - ima->ibuf->y= recty; - ima->ibuf->mall |= IB_rectfloat; - ima->ibuf->rect_float= MEM_mallocN(4*rectx*recty*sizeof(float), "viewer rect"); + /* make ibuf, and connect to ima */ + ibuf->x= rectx; + ibuf->y= recty; + imb_addrectfloatImBuf(ibuf); + ima->ok= IMA_OK_LOADED; + /* now we combine the input with ibuf */ cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/ - cbuf->rect= ima->ibuf->rect_float; + cbuf->rect= ibuf->rect_float; /* when no alpha, we can simply copy */ if(in[1]->data==NULL) { @@ -646,10 +648,11 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, else composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); + /* zbuf option */ if(in[2]->data) { CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 1); - ima->ibuf->zbuf_float= zbuf->rect; - ima->ibuf->mall |= IB_zbuffloat; + ibuf->zbuf_float= zbuf->rect; + ibuf->mall |= IB_zbuffloat; composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); @@ -674,7 +677,7 @@ static bNodeType cmp_node_viewer= { /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW, /* input sock */ cmp_node_viewer_in, /* output sock */ NULL, - /* storage */ "", + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_viewer }; @@ -706,37 +709,38 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ Image *ima= (Image *)node->id; + RenderData *rd= data; + ImBuf *ibuf; CompBuf *cbuf, *buf1, *buf2, *mask; int x, y; buf1= typecheck_compbuf(in[0]->data, CB_RGBA); buf2= typecheck_compbuf(in[1]->data, CB_RGBA); - if(ima->ibuf==NULL) - ima->ibuf= IMB_allocImBuf(buf1->x, buf1->y, 32, 0, 0); + BKE_image_user_calc_imanr(node->storage, rd->cfra, 0); - /* cleanup of viewer image */ - if(ima->ibuf->rect) { - MEM_freeN(ima->ibuf->rect); - ima->ibuf->rect= NULL; - ima->ibuf->mall &= ~IB_rect; - } - if(ima->ibuf->zbuf_float) { - MEM_freeN(ima->ibuf->zbuf_float); - ima->ibuf->zbuf_float= NULL; - ima->ibuf->mall &= ~IB_zbuffloat; + /* always returns for viewer image, but we check nevertheless */ + ibuf= BKE_image_get_ibuf(ima, node->storage); + if(ibuf==NULL) { + printf("node_composit_exec_viewer error\n"); + return; } - if(ima->ibuf->rect_float) - MEM_freeN(ima->ibuf->rect_float); - ima->ibuf->x= buf1->x; - ima->ibuf->y= buf1->y; - ima->ibuf->mall |= IB_rectfloat; - ima->ibuf->rect_float= MEM_mallocN(4*buf1->x*buf1->y*sizeof(float), "viewer rect"); + /* free all in ibuf */ + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + + /* make ibuf, and connect to ima */ + ibuf->x= buf1->x; + ibuf->y= buf1->y; + imb_addrectfloatImBuf(ibuf); + ima->ok= IMA_OK_LOADED; + /* output buf */ cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0); /* no alloc*/ - cbuf->rect= ima->ibuf->rect_float; + cbuf->rect= ibuf->rect_float; /* mask buf */ mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1); @@ -766,7 +770,7 @@ static bNodeType cmp_node_splitviewer= { /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW, /* input sock */ cmp_node_splitviewer_in, /* output sock */ NULL, - /* storage */ "", + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_splitviewer }; @@ -818,6 +822,8 @@ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **i outbuf->malloc= 0; free_compbuf(outbuf); + /* signal for imageviewer to refresh (it converts to byte rects...) */ + BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); return; } } @@ -900,140 +906,69 @@ static bNodeType cmp_node_output_file= { }; -/* **************** IMAGE ******************** */ -static bNodeSocketType cmp_node_image_out[]= { +/* **************** IMAGE (and RenderResult, multilayer image) ******************** */ + +/* output socket defines */ +#define RRES_OUT_IMAGE 0 +#define RRES_OUT_ALPHA 1 +#define RRES_OUT_Z 2 +#define RRES_OUT_NORMAL 3 +#define RRES_OUT_UV 4 +#define RRES_OUT_VEC 5 +#define RRES_OUT_RGBA 6 +#define RRES_OUT_DIFF 7 +#define RRES_OUT_SPEC 8 +#define RRES_OUT_SHADOW 9 +#define RRES_OUT_AO 10 +#define RRES_OUT_REFLECT 11 +#define RRES_OUT_REFRACT 12 +#define RRES_OUT_RADIO 13 +#define RRES_OUT_INDEXOB 14 + +static bNodeSocketType cmp_node_rlayers_out[]= { { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static int calcimanr(int cfra, NodeImageAnim *nia) -{ - - if(nia->frames==0) return nia->nr; - - cfra= cfra - nia->sfra; - - /* cyclic */ - if(nia->cyclic) - cfra= (cfra % nia->frames); - else if(cfra>=nia->frames) - cfra= nia->frames-1; - else if(cfra<0) - cfra= 0; - - cfra+= nia->nr; - - if(cfra<1) cfra= 1; - - return cfra; -} - -static void animated_image(bNode *node, int cfra) +/* note: this function is used for multilayer too, to ensure uniform + handling with BKE_image_get_ibuf() */ +static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { - Image *ima; - NodeImageAnim *nia; - int imanr; - - ima= (Image *)node->id; - nia= node->storage; - - if(nia && nia->frames && ima && ima->name) { /* frames anim or movie */ - - imanr= calcimanr(cfra, nia); - - if(nia->movie) { - char str[FILE_MAXDIR+FILE_MAXFILE]; - - strcpy(str, ima->name); - if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, cfra); - else - BLI_convertstringcode(str, G.sce, cfra); - - if(ima->anim==NULL) - ima->anim = openanim(str, IB_cmap | IB_rect); - - if (ima->anim) { - int dur = IMB_anim_get_duration(ima->anim); - - if(imanr < 0) imanr = 0; - if(imanr > (dur-1)) imanr= dur-1; - - BLI_lock_thread(LOCK_CUSTOM1); - if(ima->ibuf) IMB_freeImBuf(ima->ibuf); - ima->ibuf = IMB_anim_absolute(ima->anim, imanr); - BLI_unlock_thread(LOCK_CUSTOM1); - - /* patch for textbutton with name ima (B_NAMEIMA) */ - if(ima->ibuf) { - strcpy(ima->ibuf->name, ima->name); - ima->ok= 1; - } - } - } - else { - - if(imanr!=ima->lastframe) { - unsigned short numlen; - char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXDIR+FILE_MAXFILE]; - - strcpy(name, ima->name); - - ima->lastframe= imanr; - - BLI_stringdec(name, head, tail, &numlen); - BLI_stringenc(name, head, tail, numlen, imanr); - - ima= add_image(name); - - if(ima) { - ima->flag |= IMA_FROMANIM; - if(node->id) node->id->us--; - node->id= (ID *)ima; - - ima->ok= 1; - } - } - } - } -} - -static CompBuf *node_composit_get_image(bNode *node, RenderData *rd) -{ - Image *ima; + ImBuf *ibuf; CompBuf *stackbuf; + int type; - /* animated image? */ - if(node->storage) - animated_image(node, rd->cfra); + ibuf= BKE_image_get_ibuf(ima, iuser); + if(ibuf==NULL) + return NULL; - ima= (Image *)node->id; + if(ibuf->rect_float==NULL) + IMB_float_from_rect(ibuf); - /* test if image is OK */ - if(ima->ok==0) return NULL; - - if(ima->ibuf==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - load_image(ima, IB_rect, G.sce, rd->cfra); /* G.sce is current .blend path */ - BLI_unlock_thread(LOCK_CUSTOM1); - if(ima->ibuf==NULL) { - ima->ok= 0; - return NULL; - } - } - if(ima->ibuf->rect_float==NULL) - IMB_float_from_rect(ima->ibuf); + type= ibuf->channels; if(rd->scemode & R_COMP_CROP) { - stackbuf= get_cropped_compbuf(&rd->disprect, ima->ibuf->rect_float, ima->ibuf->x, ima->ibuf->y, CB_RGBA); + stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type); } else { /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ - stackbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_RGBA, 0); - stackbuf->rect= ima->ibuf->rect_float; + stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0); + stackbuf->rect= ibuf->rect_float; } return stackbuf; @@ -1041,39 +976,119 @@ static CompBuf *node_composit_get_image(bNode *node, RenderData *rd) static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { - Image *ima= (Image *)node->id; + ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); CompBuf *zbuf= NULL; - if(ima->ibuf && ima->ibuf->zbuf_float) { + if(ibuf && ibuf->zbuf_float) { if(rd->scemode & R_COMP_CROP) { - zbuf= get_cropped_compbuf(&rd->disprect, ima->ibuf->zbuf_float, ima->ibuf->x, ima->ibuf->y, CB_VAL); + zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL); } else { - zbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_VAL, 0); - zbuf->rect= ima->ibuf->zbuf_float; + zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0); + zbuf->rect= ibuf->zbuf_float; } } return zbuf; } +/* check if layer is available, returns pass buffer */ +static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype) +{ + RenderPass *rpass; + short index; + + for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++) + if(rpass->passtype==passtype) + break; + + if(rpass) { + CompBuf *cbuf; + + iuser->pass= index; + BKE_image_multilayer_index(ima->rr, iuser); + cbuf= node_composit_get_image(rd, ima, iuser); + + return cbuf; + } + return NULL; +} + +void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser) +{ + if(out[RRES_OUT_Z]->hasoutput) + out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z); + if(out[RRES_OUT_VEC]->hasoutput) + out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR); + if(out[RRES_OUT_NORMAL]->hasoutput) + out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL); + if(out[RRES_OUT_UV]->hasoutput) + out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV); + + if(out[RRES_OUT_RGBA]->hasoutput) + out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA); + if(out[RRES_OUT_DIFF]->hasoutput) + out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE); + if(out[RRES_OUT_SPEC]->hasoutput) + out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC); + if(out[RRES_OUT_SHADOW]->hasoutput) + out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW); + if(out[RRES_OUT_AO]->hasoutput) + out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO); + if(out[RRES_OUT_REFLECT]->hasoutput) + out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT); + if(out[RRES_OUT_REFRACT]->hasoutput) + out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT); + if(out[RRES_OUT_RADIO]->hasoutput) + out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO); + if(out[RRES_OUT_INDEXOB]->hasoutput) + out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); + +} + + static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: col, alpha */ if(node->id) { - CompBuf *stackbuf= node_composit_get_image(node, data); + RenderData *rd= data; + Image *ima= (Image *)node->id; + ImageUser *iuser= (ImageUser *)node->storage; + CompBuf *stackbuf= NULL; - /* put ibuf on stack */ - out[0]->data= stackbuf; + /* first set the right frame number in iuser */ + BKE_image_user_calc_imanr(iuser, rd->cfra, 0); + + /* force a load, we assume iuser index will be set OK anyway */ + if(ima->type==IMA_TYPE_MULTILAYER) + BKE_image_get_ibuf(ima, iuser); + if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + + if(rl) { + out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED); + + /* go over all layers */ + outputs_multilayer_get(rd, rl, out, ima, iuser); + } + } + else { + stackbuf= node_composit_get_image(rd, ima, iuser); + + /* put image on stack */ + out[0]->data= stackbuf; + + if(out[2]->hasoutput) + out[2]->data= node_composit_get_zimage(node, rd); + } + + /* alpha and preview for both types */ if(stackbuf) { if(out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - - if(out[2]->hasoutput) - out[2]->data= node_composit_get_zimage(node, data); - + generate_preview(node, stackbuf); } } @@ -1087,51 +1102,14 @@ static bNodeType cmp_node_image= { /* width+range */ 120, 80, 300, /* class+opts */ NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS, /* input sock */ NULL, - /* output sock */ cmp_node_image_out, - /* storage */ "NodeImageAnim", + /* output sock */ cmp_node_rlayers_out, + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_image }; /* **************** RENDER RESULT ******************** */ -/* output socket defines */ -#define RRES_OUT_IMAGE 0 -#define RRES_OUT_ALPHA 1 -#define RRES_OUT_Z 2 -#define RRES_OUT_NORMAL 3 -#define RRES_OUT_UV 4 -#define RRES_OUT_VEC 5 -#define RRES_OUT_RGBA 6 -#define RRES_OUT_DIFF 7 -#define RRES_OUT_SPEC 8 -#define RRES_OUT_SHADOW 9 -#define RRES_OUT_AO 10 -#define RRES_OUT_REFLECT 11 -#define RRES_OUT_REFRACT 12 -#define RRES_OUT_RADIO 13 -#define RRES_OUT_INDEXOB 14 - -static bNodeSocketType cmp_node_rlayers_out[]= { - { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { -1, 0, "" } -}; - - static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode) { float *fp= RE_RenderLayerGetPass(rl, passcode); @@ -1143,9 +1121,9 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in buftype= CB_VAL; else if(passcode==SCE_PASS_VECTOR) buftype= CB_VEC4; - else if(passcode==SCE_PASS_RGBA) + else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA)) buftype= CB_RGBA; - + if(rd->scemode & R_COMP_CROP) buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype); else { @@ -1157,6 +1135,38 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in return NULL; } +void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty) +{ + if(out[RRES_OUT_Z]->hasoutput) + out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z); + if(out[RRES_OUT_VEC]->hasoutput) + out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR); + if(out[RRES_OUT_NORMAL]->hasoutput) + out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL); + if(out[RRES_OUT_UV]->hasoutput) + out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV); + + if(out[RRES_OUT_RGBA]->hasoutput) + out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA); + if(out[RRES_OUT_DIFF]->hasoutput) + out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE); + if(out[RRES_OUT_SPEC]->hasoutput) + out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC); + if(out[RRES_OUT_SHADOW]->hasoutput) + out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW); + if(out[RRES_OUT_AO]->hasoutput) + out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO); + if(out[RRES_OUT_REFLECT]->hasoutput) + out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT); + if(out[RRES_OUT_REFRACT]->hasoutput) + out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT); + if(out[RRES_OUT_RADIO]->hasoutput) + out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO); + if(out[RRES_OUT_INDEXOB]->hasoutput) + out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); + +} + static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */ @@ -1191,33 +1201,8 @@ static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, if(out[RRES_OUT_ALPHA]->hasoutput) out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - if(out[RRES_OUT_Z]->hasoutput) - out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_Z); - if(out[RRES_OUT_VEC]->hasoutput) - out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_VECTOR); - if(out[RRES_OUT_NORMAL]->hasoutput) - out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_NORMAL); - if(out[RRES_OUT_UV]->hasoutput) - out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_UV); - - if(out[RRES_OUT_RGBA]->hasoutput) - out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_RGBA); - if(out[RRES_OUT_DIFF]->hasoutput) - out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_DIFFUSE); - if(out[RRES_OUT_SPEC]->hasoutput) - out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_SPEC); - if(out[RRES_OUT_SHADOW]->hasoutput) - out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_SHADOW); - if(out[RRES_OUT_AO]->hasoutput) - out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_AO); - if(out[RRES_OUT_REFLECT]->hasoutput) - out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_REFLECT); - if(out[RRES_OUT_REFRACT]->hasoutput) - out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_REFRACT); - if(out[RRES_OUT_RADIO]->hasoutput) - out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_RADIO); - if(out[RRES_OUT_INDEXOB]->hasoutput) - out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_INDEXOB); + + node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty); generate_preview(node, stackbuf); } @@ -3415,10 +3400,6 @@ static void node_composit_exec_dilateerode(void *data, bNode *node, bNodeStack * CompBuf *stackbuf= dupalloc_compbuf(cbuf); short i; - /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ - stackbuf->xof= cbuf->xof; - stackbuf->yof= cbuf->yof; - if (node->custom2 > 0) { // positive, dilate for (i = 0; i < node->custom2; i++) morpho_dilate(stackbuf); @@ -3427,6 +3408,9 @@ static void node_composit_exec_dilateerode(void *data, bNode *node, bNodeStack * morpho_erode(stackbuf); } + if(cbuf!=in[0]->data) + free_compbuf(cbuf); + out[0]->data= stackbuf; } } @@ -4673,6 +4657,43 @@ bNodeType *node_all_composit[]= { /* ******************* parse ************ */ +/* clumsy checking... should do dynamic outputs once */ +static void force_hidden_passes(bNode *node, int passflag) +{ + bNodeSocket *sock; + + for(sock= node->outputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_UNAVAIL; + + sock= BLI_findlink(&node->outputs, RRES_OUT_Z); + if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); + if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); + if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_UV); + if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); + if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); + if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); + if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); + if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_AO); + if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); + if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); + if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_RADIO); + if(!(passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); + if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; + +} + /* based on rules, force sockets hidden always */ void ntreeCompositForceHidden(bNodeTree *ntree) { @@ -4684,38 +4705,26 @@ void ntreeCompositForceHidden(bNodeTree *ntree) if( node->type==CMP_NODE_R_LAYERS) { Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */ SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); - if(srl) { - bNodeSocket *sock; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_Z); - if(!(srl->passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); - if(!(srl->passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); - if(!(srl->passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_UV); - if(!(srl->passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); - if(!(srl->passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); - if(!(srl->passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); - if(!(srl->passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); - if(!(srl->passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_AO); - if(!(srl->passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); - if(!(srl->passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); - if(!(srl->passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RADIO); - if(!(srl->passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); - if(!(srl->passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; + if(srl) + force_hidden_passes(node, srl->passflag); + } + else if( node->type==CMP_NODE_IMAGE) { + Image *ima= (Image *)node->id; + if(ima) { + if(ima->rr) { + ImageUser *iuser= node->storage; + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + if(rl) + force_hidden_passes(node, rl->passflag); + else + force_hidden_passes(node, 0); + } + else if(ima->type!=IMA_TYPE_MULTILAYER) { /* if ->rr not yet read we keep inputs */ + force_hidden_passes(node, 0); + } } + else + force_hidden_passes(node, 0); } } @@ -4743,8 +4752,8 @@ void ntreeCompositTagAnimated(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if(node->type==CMP_NODE_IMAGE) { - /* no actual test yet... */ - if(node->storage) + Image *ima= (Image *)node->id; + if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) NodeTagChanged(ntree, node); } else if(node->type==CMP_NODE_TIME) diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 49ad8d2ac67..0cdfda3be5d 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -402,7 +402,7 @@ there was an error or when the user desides to cancel the operation. */ -char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) { char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; char line[FILE_MAXDIR + FILE_MAXFILE + 100]; @@ -413,7 +413,7 @@ char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) if (pf != NULL) { if (how == PF_ASK) { - strcpy(menu, "UnPack file%t"); + sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE); if (strcmp(abs_name, local_name)) { switch (checkPackedFile(local_name, pf)) { @@ -460,6 +460,9 @@ char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) case -1: case PF_KEEP: break; + case PF_REMOVE: + temp= abs_name; + break; case PF_USE_LOCAL: // if file exists use it if (BLI_exists(local_name)) { @@ -596,10 +599,10 @@ int unpackImage(Image * ima, int how) if (newname != NULL) { ret_value = RET_OK; freePackedFile(ima->packedfile); - ima->packedfile = 0; + ima->packedfile = NULL; strcpy(ima->name, newname); MEM_freeN(newname); - free_image_buffers(ima); + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c656f5cdeb6..40488cf8644 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -68,6 +68,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_ipo.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 62ac911bea7..341397cba1b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -455,13 +455,17 @@ void default_tex(Tex *tex) pit = tex->plugin; if (pit) { - varstr= pit->varstr; - if(varstr) { - for(a=0; avars; a++, varstr++) { - pit->data[a] = varstr->def; - } + varstr= pit->varstr; + if(varstr) { + for(a=0; avars; a++, varstr++) { + pit->data[a] = varstr->def; } + } } + + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; + tex->iuser.frames= 100; } /* ------------------------------------------------------------------------- */ @@ -776,7 +780,7 @@ EnvMap *BKE_copy_envmap(EnvMap *env) envn= MEM_dupallocN(env); envn->ok= 0; - for(a=0; a<6; a++) envn->cube[a]= 0; + for(a=0; a<6; a++) envn->cube[a]= NULL; if(envn->ima) id_us_plus((ID *)envn->ima); return envn; @@ -786,20 +790,12 @@ EnvMap *BKE_copy_envmap(EnvMap *env) void BKE_free_envmapdata(EnvMap *env) { - Image *ima; - unsigned int a, part; + unsigned int part; for(part=0; part<6; part++) { - ima= env->cube[part]; - if(ima) { - if(ima->ibuf) IMB_freeImBuf(ima->ibuf); - - for(a=0; amipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - } - MEM_freeN(ima); - env->cube[part]= 0; - } + if(env->cube[part]) + IMB_freeImBuf(env->cube[part]); + env->cube[part]= NULL; } env->ok= 0; } diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 1a35cad3a03..58bd3fd6bf6 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -96,7 +96,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, void BLI_make_exist(char *dir); void BLI_make_existing_file(char *name); void BLI_split_dirfile(const char *string, char *dir, char *file); -int BLI_testextensie(char *str, char *ext); +int BLI_testextensie(const char *str, const char *ext); void addlisttolist(ListBase *list1, ListBase *list2); void BLI_insertlink(struct ListBase *listbase, void *vprevlink, void *vnewlink); void * BLI_findlink(struct ListBase *listbase, int number); @@ -193,7 +193,7 @@ char* BLI_strdupn(char *str, int len); * the size of dst) * @retval Returns dst */ -char* BLI_strncpy(char *dst, char *src, int maxncpy); +char* BLI_strncpy(char *dst, const char *src, int maxncpy); /** * Compare two strings diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index fbbc42115d5..e52c573eec7 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -81,7 +81,14 @@ void BLI_gsqueue_pop(GSQueue *gq, void *item_r) } void BLI_gsqueue_push(GSQueue *gq, void *item) { - GSQueueElem *elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push"); + GSQueueElem *elem; + + /* compare: prevent events added double in row */ + if (!BLI_gsqueue_is_empty(gq)) { + if(0==memcmp(item, &gq->head[1], gq->elem_size)) + return; + } + elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push"); memcpy(&elem[1], item, gq->elem_size); elem->next= NULL; diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 9fd5b40878e..29e15068f15 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -638,7 +638,7 @@ char *BLI_strdup(char *str) { return BLI_strdupn(str, strlen(str)); } -char *BLI_strncpy(char *dst, char *src, int maxncpy) { +char *BLI_strncpy(char *dst, const char *src, int maxncpy) { int srclen= strlen(src); int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen; @@ -1117,7 +1117,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, BLI_clean(string); } -int BLI_testextensie(char *str, char *ext) +int BLI_testextensie(const char *str, const char *ext) { short a, b; int retval; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 342f3232d22..48eb6ae8e55 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -120,7 +120,7 @@ #include "BKE_effect.h" // for give_parteff #include "BKE_global.h" // for G #include "BKE_group.h" -#include "BKE_property.h" // for get_property +#include "BKE_image.h" #include "BKE_lattice.h" #include "BKE_library.h" // for wich_libbase #include "BKE_main.h" // for Main @@ -128,6 +128,7 @@ #include "BKE_modifier.h" #include "BKE_node.h" // for tree type defines #include "BKE_object.h" +#include "BKE_property.h" // for get_property #include "BKE_sca.h" // for init_actuator #include "BKE_scene.h" #include "BKE_softbody.h" // sbNew() @@ -1108,8 +1109,9 @@ void blo_make_image_pointer_map(FileData *fd) fd->imamap= oldnewmap_new(); for(;ima; ima= ima->id.next) { - if(ima->ibuf) - oldnewmap_insert(fd->imamap, ima->ibuf, ima->ibuf, 0); + Link *ibuf= ima->ibufs.first; + for(; ibuf; ibuf= ibuf->next) + oldnewmap_insert(fd->imamap, ibuf, ibuf, 0); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -1136,11 +1138,15 @@ void blo_end_image_pointer_map(FileData *fd) } for(;ima; ima= ima->id.next) { - if(ima->ibuf) { - ima->ibuf= newimaadr(fd, ima->ibuf); - /* this mirrors direct_link_image */ - if(ima->ibuf==NULL) + Link *ibuf, *next; + + /* this mirrors direct_link_image */ + for(ibuf= ima->ibufs.first; ibuf; ibuf= next) { + next= ibuf->next; + if(NULL==newimaadr(fd, ibuf)) { /* so was restored */ + BLI_remlink(&ima->ibufs, ibuf); ima->bindcode= 0; + } } } for(; sce; sce= sce->id.next) { @@ -1213,11 +1219,11 @@ static void link_list(FileData *fd, ListBase *lb) /* only direct data */ { Link *ln, *prev; - if(lb->first==0) return; + if(lb->first==NULL) return; lb->first= newdataadr(fd, lb->first); ln= lb->first; - prev= 0; + prev= NULL; while(ln) { ln->next= newdataadr(fd, ln->next); ln->prev= prev; @@ -1480,9 +1486,12 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) /* could be handlerized at some point */ if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)) direct_link_curvemapping(fd, node->storage); - else if(ntree->type==NTREE_COMPOSIT && (node->type==CMP_NODE_TIME || node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB)) - direct_link_curvemapping(fd, node->storage); - + else if(ntree->type==NTREE_COMPOSIT) { + if( ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB)) + direct_link_curvemapping(fd, node->storage); + else if(ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) + ((ImageUser *)node->storage)->ok= 1; + } } link_list(fd, &node->inputs); link_list(fd, &node->outputs); @@ -2167,16 +2176,38 @@ static void lib_link_image(FileData *fd, Main *main) } } +static void link_ibuf_list(FileData *fd, ListBase *lb) +{ + Link *ln, *prev; + + if(lb->first==NULL) return; + + lb->first= newimaadr(fd, lb->first); + ln= lb->first; + prev= NULL; + while(ln) { + ln->next= newimaadr(fd, ln->next); + ln->prev= prev; + prev= ln; + ln= ln->next; + } + lb->last= prev; +} + static void direct_link_image(FileData *fd, Image *ima) { /* for undo system, pointers could be restored */ - ima->ibuf= newimaadr(fd, ima->ibuf); - /* if restored, we keep the binded opengl index */ - if(ima->ibuf==NULL) + if(fd->imamap) + link_ibuf_list(fd, &ima->ibufs); + else + ima->ibufs.first= ima->ibufs.last= NULL; + + /* if not restored, we keep the binded opengl index */ + if(ima->ibufs.first==NULL) ima->bindcode= 0; - memset(ima->mipmap, 0, sizeof(ima->mipmap)); ima->anim= NULL; + ima->rr= NULL; ima->repbind= NULL; ima->packedfile = direct_link_packedfile(fd, ima->packedfile); @@ -2319,10 +2350,11 @@ static void direct_link_texture(FileData *fd, Tex *tex) tex->coba= newdataadr(fd, tex->coba); tex->env= newdataadr(fd, tex->env); if(tex->env) { - tex->env->ima= 0; + tex->env->ima= NULL; memset(tex->env->cube, 0, 6*sizeof(void *)); tex->env->ok= 0; } + tex->iuser.ok= 1; } @@ -3304,10 +3336,8 @@ static void lib_link_screen_sequence_ipos(Main *main) bScreen *sc; ScrArea *sa; - sc= main->screen.first; - while(sc) { - sa= sc->areabase.first; - while(sa) { + for(sc= main->screen.first; sc; sc= sc->id.next) { + for(sa= sc->areabase.first; sa; sa= sa->next) { SpaceLink *sl; for (sl= sa->spacedata.first; sl; sl= sl->next) { if(sl->spacetype == SPACE_IPO) { @@ -3317,9 +3347,7 @@ static void lib_link_screen_sequence_ipos(Main *main) } } } - sa= sa->next; } - sc= sc->id.next; } } @@ -3332,8 +3360,7 @@ static void lib_link_screen(FileData *fd, Main *main) bScreen *sc; ScrArea *sa; - sc= main->screen.first; - while(sc) { + for(sc= main->screen.first; sc; sc= sc->id.next) { if(sc->id.flag & LIB_NEEDLINK) { sc->id.us= 1; sc->scene= newlibadr(fd, sc->id.lib, sc->scene); @@ -3356,8 +3383,6 @@ static void lib_link_screen(FileData *fd, Main *main) if(v3d->bgpic) { v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima); - v3d->bgpic->tex= newlibadr_us(fd, sc->id.lib, v3d->bgpic->tex); - v3d->bgpic->rect= NULL; } if(v3d->localvd) { v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera); @@ -3384,9 +3409,11 @@ static void lib_link_screen(FileData *fd, Main *main) else if(sl->spacetype==SPACE_FILE) { SpaceFile *sfile= (SpaceFile *)sl; - sfile->filelist= 0; - sfile->libfiledata= 0; - sfile->returnfunc= 0; + sfile->filelist= NULL; + sfile->libfiledata= NULL; + sfile->returnfunc= NULL; + sfile->menup= NULL; + sfile->pupmenu= NULL; } else if(sl->spacetype==SPACE_IMASEL) { check_imasel_copy((SpaceImaSel *)sl); @@ -3446,7 +3473,6 @@ static void lib_link_screen(FileData *fd, Main *main) } sc->id.flag -= LIB_NEEDLINK; } - sc= sc->id.next; } } @@ -3484,8 +3510,7 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene) bScreen *sc; ScrArea *sa; - sc= newmain->screen.first; - while(sc) { + for(sc= newmain->screen.first; sc; sc= sc->id.next) { sc->scene= curscene; @@ -3514,9 +3539,6 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene) if(v3d->bgpic) { v3d->bgpic->ima= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->ima, 1); - v3d->bgpic->tex= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->tex, 1); - if(v3d->bgpic->rect) MEM_freeN(v3d->bgpic->rect); - v3d->bgpic->rect= NULL; } if(v3d->localvd) { Base *base; @@ -3624,10 +3646,7 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene) } sa= sa->next; } - - sc= sc->id.next; } - } static void direct_link_screen(FileData *fd, bScreen *sc) @@ -3693,6 +3712,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc) if (sl->spacetype==SPACE_VIEW3D) { View3D *v3d= (View3D*) sl; v3d->bgpic= newdataadr(fd, v3d->bgpic); + if(v3d->bgpic) + v3d->bgpic->iuser.ok= 1; v3d->localvd= newdataadr(fd, v3d->localvd); v3d->afterdraw.first= v3d->afterdraw.last= NULL; v3d->clipbb= newdataadr(fd, v3d->clipbb); @@ -3723,7 +3744,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sima->cumap= newdataadr(fd, sima->cumap); if(sima->cumap) direct_link_curvemapping(fd, sima->cumap); - sima->info_str= NULL; + sima->info_str= sima->info_spare= NULL; + sima->spare= NULL; + sima->iuser.ok= 1; } else if(sl->spacetype==SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; @@ -4049,10 +4072,6 @@ static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg) bfd->displaymode= fg->displaymode; bfd->globalf= fg->globalf; - bfd->main->subversionfile= fg->subversion; - bfd->main->minversionfile= fg->minversion; - bfd->main->minsubversionfile= fg->minsubversion; - bfd->curscreen= newlibadr(fd, 0, fg->curscreen); bfd->curscene= newlibadr(fd, 0, fg->curscene); // this happens in files older than 2.35 @@ -4240,6 +4259,40 @@ static void customdata_version_242(Mesh *me) mesh_update_customdata_pointers(me); } +/* struct NodeImageAnim moved to ImageUser, and we make it default available */ +static void do_version_ntree_242_2(bNodeTree *ntree) +{ + bNode *node; + + if(ntree->type==NTREE_COMPOSIT) { + for(node= ntree->nodes.first; node; node= node->next) { + if(ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + /* only image had storage */ + if(node->storage) { + NodeImageAnim *nia= node->storage; + ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "ima user node"); + + iuser->frames= nia->frames; + iuser->sfra= nia->sfra; + iuser->offset= nia->nr-1; + iuser->cycl= nia->cyclic; + iuser->fie_ima= 2; + iuser->ok= 1; + + node->storage= iuser; + MEM_freeN(nia); + } + else { + ImageUser *iuser= node->storage= MEM_callocN(sizeof(ImageUser), "node image user"); + iuser->sfra= 1; + iuser->fie_ima= 2; + iuser->ok= 1; + } + } + } + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -4258,10 +4311,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if(tex->imaflag & TEX_ANIM5) { - tex->imaflag |= TEX_MORKPATCH; - tex->imaflag |= TEX_ANTIALI; - } } tex= tex->id.next; } @@ -6169,7 +6218,71 @@ static void do_versions(FileData *fd, Library *lib, Main *main) sort_shape_fix(main); /* now, subversion control! */ - if(main->subversionfile < 1) { + if(main->subversionfile < 3) { + bScreen *sc; + Image *ima; + Tex *tex; + Scene *sce; + bNodeTree *ntree; + + /* Image refactor initialize */ + for(ima= main->image.first; ima; ima= ima->id.next) { + ima->source= IMA_SRC_FILE; + ima->type= IMA_TYPE_IMAGE; + + ima->gen_x= 256; ima->gen_y= 256; + ima->gen_type= 1; + + if(0==strncmp(ima->id.name+2, "Viewer Node", sizeof(ima->id.name+2))) { + ima->source= IMA_SRC_VIEWER; + ima->type= IMA_TYPE_COMPOSITE; + } + if(0==strncmp(ima->id.name+2, "Render Result", sizeof(ima->id.name+2))) { + ima->source= IMA_SRC_VIEWER; + ima->type= IMA_TYPE_R_RESULT; + } + + } + for(tex= main->tex.first; tex; tex= tex->id.next) { + if(tex->type==TEX_IMAGE && tex->ima) { + ima= newlibadr(fd, lib, tex->ima); + if(tex->imaflag & TEX_ANIM5_) + ima->source= IMA_SRC_MOVIE; + if(tex->imaflag & TEX_FIELDS_) + ima->flag |= IMA_FIELDS; + if(tex->imaflag & TEX_STD_FIELD_) + ima->flag |= IMA_STD_FIELD; + if(tex->imaflag & TEX_ANTIALI_) + ima->flag |= IMA_ANTIALI; + } + tex->iuser.frames= tex->frames; + tex->iuser.fie_ima= tex->fie_ima; + tex->iuser.offset= tex->offset; + tex->iuser.sfra= tex->sfra; + tex->iuser.cycl= (tex->imaflag & TEX_ANIMCYCLIC_)!=0; + } + for(sce= main->scene.first; sce; sce= sce->id.next) { + if(sce->nodetree) + do_version_ntree_242_2(sce->nodetree); + } + for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) + do_version_ntree_242_2(ntree); + + for(sc= main->screen.first; sc; sc= sc->id.next) { + ScrArea *sa; + for(sa= sc->areabase.first; sa; sa= sa->next) { + SpaceLink *sl; + for (sl= sa->spacedata.first; sl; sl= sl->next) { + if(sl->spacetype==SPACE_IMAGE) + ((SpaceImage *)sl)->iuser.fie_ima= 2; + else if(sl->spacetype==SPACE_VIEW3D) { + View3D *v3d= (View3D *)sl; + if(v3d->bgpic) + v3d->bgpic->iuser.fie_ima= 2; + } + } + } + } } } @@ -6252,6 +6365,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r) case REND: if (bhead->code==GLOB) { fg= read_struct(fd, bhead, "Global"); + /* set right away */ + bfd->main->subversionfile= fg->subversion; + bfd->main->minversionfile= fg->minversion; + bfd->main->minsubversionfile= fg->minsubversion; } bhead = blo_nextbhead(fd, bhead); break; diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 02b3557c094..60177f2c996 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -315,6 +315,7 @@ void IMB_antialias(struct ImBuf * ibuf); void IMB_filter(struct ImBuf *ibuf); void IMB_filterN(struct ImBuf *out, struct ImBuf *in); void IMB_filter_extend(struct ImBuf *ibuf); +void IMB_makemipmap(struct ImBuf *ibuf, int use_filter); /** * @@ -537,6 +538,7 @@ void imb_freerectImBuf(struct ImBuf * ibuf); short imb_addrectfloatImBuf(struct ImBuf * ibuf); void imb_freerectfloatImBuf(struct ImBuf * ibuf); +void imb_freemipmapImBuf(struct ImBuf * ibuf); #ifdef WITH_QUICKTIME /** diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 586dedc54e8..f5487bb9ac0 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -56,6 +56,8 @@ struct _AviMovie; struct Mdec; +#define IB_MIPMAP_LEVELS 10 + /** * \brief The basic imbuf type * \ingroup imbuf @@ -70,36 +72,41 @@ struct Mdec; * * Also, that iff.h needs to be in the final release "plugins/include" dir, too! */ -typedef struct ImBuf{ - short x, y; /**< width and Height of our image buffer */ - short skipx; /**< Width in ints to get to the next scanline */ +typedef struct ImBuf { + struct ImBuf *next, *prev; /**< allow lists of ImBufs, for caches or flipbooks */ + short x, y; /**< width and Height of our image buffer */ + short skipx; /**< Width in ints to get to the next scanline */ unsigned char depth; /**< Active amount of bits/bitplanes */ unsigned char cbits; /**< Amount of active bits in cmap */ unsigned short mincol; /**< smallest color in colormap */ unsigned short maxcol; /**< Largest color in colormap */ - int type; /**< 0=abgr, 1=bitplanes */ - int ftype; /**< File type we are going to save as */ + int type; /**< 0=abgr, 1=bitplanes */ + int ftype; /**< File type we are going to save as */ unsigned int *cmap; /**< Color map data. */ unsigned int *rect; /**< pixel values stored here */ unsigned int **planes; /**< bitplanes */ - int flags; /**< Controls which components should exist. */ - int mall; /**< what is malloced internal, and can be freed */ + int flags; /**< Controls which components should exist. */ + int mall; /**< what is malloced internal, and can be freed */ short xorig, yorig; /**< Cordinates of first pixel of an image used in some formats (example: targa) */ char name[1023]; /**< The file name assocated with this image */ char namenull; /**< Unused don't want to remove it thought messes things up */ - int userflags; /**< Used to set imbuf to Dirty and other stuff */ - int *zbuf; /**< z buffer data, original zbuffer */ - float *zbuf_float; /**< z buffer data, camera coordinates */ + int userflags; /**< Used to set imbuf to Dirty and other stuff */ + int *zbuf; /**< z buffer data, original zbuffer */ + float *zbuf_float; /**< z buffer data, camera coordinates */ void *userdata; unsigned char *encodedbuffer; /**< Compressed image only used with png currently */ unsigned int encodedsize; /**< Size of data written to encodedbuffer */ unsigned int encodedbuffersize; /**< Size of encodedbuffer */ float *rect_float; /**< floating point Rect equivilant */ + int channels; /**< amount of channels in rect_float (0 = 4 channel default) */ float dither; /**< random dither value, for conversion from float -> byte rect */ struct MEM_CacheLimiterHandle_s * c_handle; /**< handle for cache limiter */ - int refcounter; /**< Refcounter for multiple users */ + int refcounter; /**< Refcounter for multiple users */ + int index; /**< reference index for ImBuf lists */ + + struct ImBuf *mipmap[IB_MIPMAP_LEVELS]; /**< MipMap levels, a series of halved images */ } ImBuf; /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */ @@ -138,8 +145,9 @@ typedef enum { #define IB_zbuf (1 << 13) #define IB_mem (1 << 14) -#define IB_rectfloat (1 << 15) -#define IB_zbuffloat (1 << 16) +#define IB_rectfloat (1 << 15) +#define IB_zbuffloat (1 << 16) +#define IB_multilayer (1 << 17) /* * The bit flag is stored in the ImBuf.ftype variable. diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 30e97328e7c..003d377389b 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -62,6 +62,17 @@ void imb_freeplanesImBuf(struct ImBuf * ibuf) ibuf->mall &= ~IB_planes; } +void imb_freemipmapImBuf(struct ImBuf * ibuf) +{ + int a; + + for(a=0; amipmap[a]) IMB_freeImBuf(ibuf->mipmap[a]); + ibuf->mipmap[a]= NULL; + } +} + +/* any free rect frees mipmaps to be sure, creation is in render on first request */ void imb_freerectfloatImBuf(struct ImBuf * ibuf) { if (ibuf==NULL) return; @@ -73,10 +84,13 @@ void imb_freerectfloatImBuf(struct ImBuf * ibuf) } } + imb_freemipmapImBuf(ibuf); + ibuf->rect_float= NULL; ibuf->mall &= ~IB_rectfloat; } +/* any free rect frees mipmaps to be sure, creation is in render on first request */ void imb_freerectImBuf(struct ImBuf * ibuf) { if (ibuf==NULL) return; @@ -87,6 +101,8 @@ void imb_freerectImBuf(struct ImBuf * ibuf) } } + imb_freemipmapImBuf(ibuf); + ibuf->rect= NULL; ibuf->mall &= ~IB_rect; } @@ -363,7 +379,8 @@ struct ImBuf *IMB_allocImBuf(short x, short y, uchar d, unsigned int flags, ucha ibuf->y= y; ibuf->depth= d; ibuf->ftype= TGA; - + ibuf->channels= 4; /* float option, is set to other values when buffers get assigned */ + if (flags & IB_rect){ if (imb_addrectImBuf(ibuf)==FALSE){ IMB_freeImBuf(ibuf); @@ -407,7 +424,7 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) { struct ImBuf *ibuf2, tbuf; int flags = 0; - int x, y; + int a, x, y; if (ibuf1 == NULL) return NULL; @@ -452,6 +469,8 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) tbuf.encodedbuffer = ibuf2->encodedbuffer; tbuf.zbuf= NULL; tbuf.zbuf_float= NULL; + for(a=0; amall; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index c0018d0b336..a4fab4a3572 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -181,7 +181,7 @@ void IMB_rect_from_float(struct ImBuf *ibuf) /* quick method to convert floatbuf to byte */ float *tof = ibuf->rect_float; float dither= ibuf->dither; - int i; + int i, channels= ibuf->channels; unsigned char *to = (unsigned char *) ibuf->rect; if(tof==NULL) return; @@ -190,14 +190,26 @@ void IMB_rect_from_float(struct ImBuf *ibuf) to = (unsigned char *) ibuf->rect; } - if(dither==0.0f) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = FTOCHAR(tof[3]); - to += 4; - tof += 4; + if(dither==0.0f || channels!=4) { + if(channels==1) { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) + to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); + } + else if(channels==3) { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { + to[0] = FTOCHAR(tof[0]); + to[1] = FTOCHAR(tof[1]); + to[2] = FTOCHAR(tof[2]); + to[3] = 255; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { + to[0] = FTOCHAR(tof[0]); + to[1] = FTOCHAR(tof[1]); + to[2] = FTOCHAR(tof[2]); + to[3] = FTOCHAR(tof[3]); + } } } else { diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 343211eb6b0..fd9dac1af2b 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -302,3 +302,28 @@ void IMB_filter_extend(struct ImBuf *ibuf) } } +void IMB_makemipmap(ImBuf *ibuf, int use_filter) +{ + ImBuf *hbuf= ibuf; + int minsize, curmap=0; + + minsize= ibuf->xy?ibuf->x:ibuf->y; + + while(minsize>10 && curmapx, hbuf->y, 32, IB_rect, 0); + IMB_filterN(nbuf, hbuf); + ibuf->mipmap[curmap]= IMB_onehalf(nbuf); + IMB_freeImBuf(nbuf); + } + else { + ibuf->mipmap[curmap]= IMB_onehalf(hbuf); + } + hbuf= ibuf->mipmap[curmap]; + + curmap++; + minsize= hbuf->xy?hbuf->x:hbuf->y; + } +} + + diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 3027f9508cf..25ca958afdb 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -343,37 +343,69 @@ short imb_save_openexr(struct ImBuf *ibuf, char *name, int flags) } } -/* ********************* Tile file support ************************************ */ +/* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ + +/* naming rules: + - parse name from right to left + - last character is channel ID, 1 char like 'A' 'R' 'G' 'B' 'X' 'Y' 'Z' 'W' 'U' 'V' + - separated with a dot; the Pass name (like "Depth", "Color", "Diffuse" or "Combined") + - separated with a dot: the Layer name (like "Lamp1" or "Walls" or "Characters") +*/ + +static ListBase exrhandles= {NULL, NULL}; typedef struct ExrHandle { + struct ExrHandle *next, *prev; + InputFile *ifile; TiledOutputFile *tofile; OutputFile *ofile; int tilex, tiley; int width, height; - ListBase channels; + + ListBase channels; /* flattened out, ExrChannel */ + ListBase layers; /* hierarchical, pointing in end to ExrChannel */ } ExrHandle; -#define CHANMAXNAME 64 +/* flattened out channel */ typedef struct ExrChannel { struct ExrChannel *next, *prev; - char name[2*CHANMAXNAME + 1]; - int xstride, ystride; - float *rect; + + char name[EXR_TOT_MAXNAME+1]; /* full name of layer+pass */ + int xstride, ystride; /* step to next pixel, to next scanline */ + float *rect; /* first pointer to write in */ + char chan_id; /* quick lookup of channel char */ } ExrChannel; -/* not threaded! write one tiled file at a time */ + +/* hierarchical; layers -> passes -> channels[] */ +typedef struct ExrPass { + struct ExrPass *next, *prev; + char name[EXR_PASS_MAXNAME]; + int totchan; + float *rect; + struct ExrChannel *chan[EXR_PASS_MAXCHAN]; + char chan_id[EXR_PASS_MAXCHAN]; +} ExrPass; + +typedef struct ExrLayer { + struct ExrLayer *next, *prev; + char name[EXR_LAY_MAXNAME+1]; + ListBase passes; +} ExrLayer; + +/* ********************** */ + void *IMB_exr_get_handle(void) { - static ExrHandle data; - - memset(&data, sizeof(ExrHandle), 0); - - return &data; + ExrHandle *data= (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle"); + BLI_addtail(&exrhandles, data); + return data; } -/* still clumsy name handling, layers/channels can be ordered as list in list later */ -void IMB_exr_add_channel(void *handle, const char *layname, const char *channame) +/* adds flattened ExrChannels */ +/* xstride, ystride and rect can be done in set_channel too, for tile writing */ +void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) { ExrHandle *data= (ExrHandle *)handle; ExrChannel *echan; @@ -381,14 +413,19 @@ void IMB_exr_add_channel(void *handle, const char *layname, const char *channame echan= (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr tile channel"); if(layname) { - char lay[CHANMAXNAME], chan[CHANMAXNAME]; - strncpy(lay, layname, CHANMAXNAME-1); - strncpy(chan, channame, CHANMAXNAME-1); + char lay[EXR_LAY_MAXNAME+1], pass[EXR_PASS_MAXNAME+1]; + BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); + BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); - sprintf(echan->name, "%s.%s", lay, chan); + sprintf(echan->name, "%s.%s", lay, pass); } else - strncpy(echan->name, channame, 2*CHANMAXNAME); + BLI_strncpy(echan->name, passname, EXR_TOT_MAXNAME-1); + + echan->xstride= xstride; + echan->ystride= ystride; + echan->rect= rect; + // printf("added channel %s\n", echan->name); BLI_addtail(&data->channels, echan); } @@ -405,7 +442,9 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height) for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) header.channels().insert (echan->name, Channel (FLOAT)); - header.insert ("comments", StringAttribute ("Blender MultiChannel")); + header.compression() = RLE_COMPRESSION; + + header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43")); data->ofile = new OutputFile(filename, header); } @@ -426,13 +465,14 @@ void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height header.setTileDescription (TileDescription (tilex, tiley, ONE_LEVEL)); header.lineOrder() = RANDOM_Y, - header.compression() = NO_COMPRESSION; + header.compression() = RLE_COMPRESSION; - header.insert ("comments", StringAttribute ("Blender MultiChannel")); + header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43")); data->tofile = new TiledOutputFile(filename, header); } +/* read from file */ int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) { ExrHandle *data= (ExrHandle *)handle; @@ -447,7 +487,7 @@ int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) const ChannelList &channels = data->ifile->header().channels(); for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) - IMB_exr_add_channel(data, NULL, i.name()); + IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL); return 1; } @@ -456,21 +496,21 @@ int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) } /* still clumsy name handling, layers/channels can be ordered as list in list later */ -void IMB_exr_set_channel(void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) +void IMB_exr_set_channel(void *handle, char *layname, char *passname, int xstride, int ystride, float *rect) { ExrHandle *data= (ExrHandle *)handle; ExrChannel *echan; - char name[2*CHANMAXNAME + 1]; + char name[EXR_TOT_MAXNAME + 1]; if(layname) { - char lay[CHANMAXNAME], chan[CHANMAXNAME]; - strncpy(lay, layname, CHANMAXNAME-1); - strncpy(chan, channame, CHANMAXNAME-1); + char lay[EXR_LAY_MAXNAME+1], pass[EXR_PASS_MAXNAME+1]; + BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); + BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); - sprintf(name, "%s.%s", lay, chan); + sprintf(name, "%s.%s", lay, pass); } else - strncpy(name, channame, 2*CHANMAXNAME); + BLI_strncpy(name, passname, EXR_TOT_MAXNAME-1); for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) @@ -540,11 +580,38 @@ void IMB_exr_read_channels(void *handle) data->ifile->readPixels (0, data->height-1); } +void IMB_exr_multilayer_convert(void *handle, void *base, + void * (*addlayer)(void *base, char *str), + void (*addpass)(void *base, void *lay, char *str, + float *rect, int totchan, char *chan_id)) +{ + ExrHandle *data= (ExrHandle *)handle; + ExrLayer *lay; + ExrPass *pass; + + if(data->layers.first==NULL) { + printf("cannot convert multilayer, no layers in handle\n"); + return; + } + + for(lay= (ExrLayer *)data->layers.first; lay; lay= lay->next) { + void *laybase= addlayer(base, lay->name); + if(laybase) { + for(pass= (ExrPass *)lay->passes.first; pass; pass= pass->next) { + addpass(base, laybase, pass->name, pass->rect, pass->totchan, pass->chan_id); + pass->rect= NULL; + } + } + } +} + void IMB_exr_close(void *handle) { ExrHandle *data= (ExrHandle *)handle; ExrChannel *echan; + ExrLayer *lay; + ExrPass *pass; if(data->ifile) delete data->ifile; @@ -558,6 +625,191 @@ void IMB_exr_close(void *handle) data->tofile= NULL; BLI_freelistN(&data->channels); + + for(lay= (ExrLayer *)data->layers.first; lay; lay= lay->next) { + for(pass= (ExrPass *)lay->passes.first; pass; pass= pass->next) + if(pass->rect) + MEM_freeN(pass->rect); + BLI_freelistN(&lay->passes); + } + BLI_freelistN(&data->layers); + + BLI_remlink(&exrhandles, data); + MEM_freeN(data); +} + +/* ********* */ + +static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *passname) +{ + int plen, len= strlen(echan->name); + + if(len < 4) { + printf("multilayer read: name too short: %s\n", echan->name); + return 0; + } + if(echan->name[len-2]!='.') { + printf("multilayer read: name has no Channel: %s\n", echan->name); + return 0; + } + echan->chan_id= echan->name[len-1]; + + len-= 3; + while(len>=0) { + if(echan->name[len]=='.') + break; + len--; + } + BLI_strncpy(passname, echan->name+len+1, EXR_PASS_MAXNAME); + plen= strlen(passname); + if(plen < 3) { + printf("multilayer read: should not happen: %s\n", echan->name); + return 0; + } + passname[plen-2]= 0; + + if(len<1) + layname[0]= 0; + else { + BLI_strncpy(layname, echan->name, EXR_LAY_MAXNAME); + layname[len]= 0; + } + // printf("found lay %s pass %s chan %c\n", layname, passname, echan->chan_id); +} + +static ExrLayer *imb_exr_get_layer(ListBase *lb, char *layname) +{ + ExrLayer *lay; + + for(lay= (ExrLayer *)lb->first; lay; lay= lay->next) { + if( strcmp(lay->name, layname)==0 ) + return lay; + } + lay= (ExrLayer *)MEM_callocN(sizeof(ExrLayer), "exr layer"); + BLI_addtail(lb, lay); + BLI_strncpy(lay->name, layname, EXR_LAY_MAXNAME); + + return lay; +} + +static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname) +{ + ExrPass *pass; + + for(pass= (ExrPass *)lb->first; pass; pass= pass->next) { + if( strcmp(pass->name, passname)==0 ) + return pass; + } + + pass= (ExrPass *)MEM_callocN(sizeof(ExrPass), "exr pass"); + + if(strcmp(passname, "Combined")==0) + BLI_addhead(lb, pass); + else + BLI_addtail(lb, pass); + + BLI_strncpy(pass->name, passname, EXR_LAY_MAXNAME); + + return pass; +} + +/* creates channels, makes a hierarchy and assigns memory to channels */ +static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) +{ + ExrLayer *lay; + ExrPass *pass; + ExrChannel *echan; + ExrHandle *data= (ExrHandle *)IMB_exr_get_handle(); + int a; + char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME]; + + data->ifile= file; + data->width= width; + data->height= height; + + const ChannelList &channels = data->ifile->header().channels(); + + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) + IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL); + + /* now try to sort out how to assign memory to the channels */ + /* first build hierarchical layer list */ + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) { + if( imb_exr_split_channel_name(echan, layname, passname) ) { + ExrLayer *lay= imb_exr_get_layer(&data->layers, layname); + ExrPass *pass= imb_exr_get_pass(&lay->passes, passname); + + pass->chan[pass->totchan]= echan; + pass->totchan++; + if(pass->totchan>=EXR_PASS_MAXCHAN) + break; + } + } + if(echan) { + printf("error, too many channels in one pass: %s\n", echan->name); + IMB_exr_close(data); + return NULL; + } + + /* with some heuristics, try to merge the channels in buffers */ + for(lay= (ExrLayer *)data->layers.first; lay; lay= lay->next) { + for(pass= (ExrPass *)lay->passes.first; pass; pass= pass->next) { + if(pass->totchan) { + pass->rect= (float *)MEM_mapallocN(width*height*pass->totchan*sizeof(float), "pass rect"); + if(pass->totchan==1) { + echan= pass->chan[0]; + echan->rect= pass->rect; + echan->xstride= 1; + echan->ystride= width; + pass->chan_id[0]= echan->chan_id; + } + else { + char lookup[256]; + + memset(lookup, 0, sizeof(lookup)); + + /* we can have RGB(A), XYZ(W), UVA */ + if(pass->totchan==3 || pass->totchan==4) { + if(pass->chan[0]->chan_id=='B' || pass->chan[1]->chan_id=='B' || pass->chan[2]->chan_id=='B') { + lookup['R']= 0; + lookup['G']= 1; + lookup['B']= 2; + lookup['A']= 3; + } + else if(pass->chan[0]->chan_id=='Y' || pass->chan[1]->chan_id=='Y' || pass->chan[2]->chan_id=='Y') { + lookup['X']= 0; + lookup['Y']= 1; + lookup['Z']= 2; + lookup['W']= 3; + } + else { + lookup['U']= 0; + lookup['V']= 1; + lookup['A']= 2; + } + for(a=0; atotchan; a++) { + echan= pass->chan[a]; + echan->rect= pass->rect + lookup[echan->chan_id]; + echan->xstride= pass->totchan; + echan->ystride= width*pass->totchan; + pass->chan_id[ lookup[echan->chan_id] ]= echan->chan_id; + } + } + else { /* unknown */ + for(a=0; atotchan; a++) { + echan= pass->chan[a]; + echan->rect= pass->rect + a; + echan->xstride= pass->totchan; + echan->ystride= width*pass->totchan; + pass->chan_id[a]= echan->chan_id; + } + } + } + } + } + } + + return data; } @@ -598,9 +850,9 @@ static int exr_has_zbuffer(InputFile *file) static int exr_is_renderresult(InputFile *file) { - const StringAttribute *comments= file->header().findTypedAttribute("comments"); + const StringAttribute *comments= file->header().findTypedAttribute("BlenderMultiChannel"); if(comments) - if(comments->value() == "Blender MultiChannel") +// if(comments->value() == "Blender MultiChannel") return 1; return 0; } @@ -615,6 +867,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) try { Mem_IStream membuf(mem, size); + int is_multi; file = new InputFile(membuf); Box2i dw = file->header().dataWindow(); @@ -625,53 +878,70 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) // dw.min.x, dw.min.y, dw.max.x, dw.max.y); //exr_print_filecontents(file); - int flipped= exr_is_renderresult(file); - ibuf = IMB_allocImBuf(width, height, 32, 0, 0); + is_multi= exr_is_renderresult(file); - if (ibuf) + /* do not make an ibuf when */ + if(is_multi && !(flags & IB_test) && !(flags & IB_multilayer)) { + printf("Error: can't process EXR multilayer file\n"); + } + else { + + ibuf = IMB_allocImBuf(width, height, 32, 0, 0); ibuf->ftype = OPENEXR; if (!(flags & IB_test)) { - FrameBuffer frameBuffer; - float *first; - int xstride = sizeof(float) * 4; - int ystride = flipped ? xstride*width : - xstride*width; - - imb_addrectfloatImBuf(ibuf); - - /* inverse correct first pixel for datawindow coordinates (- dw.min.y because of y flip) */ - first= ibuf->rect_float - 4*(dw.min.x - dw.min.y*width); - /* but, since we read y-flipped (negative y stride) we move to last scanline */ - if(!flipped) first+= 4*(height-1)*width; - - frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); - frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); - /* 1.0 is fill value */ - frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); - - if(exr_has_zbuffer(file)) + if(is_multi) /* only enters with IB_multilayer flag set */ { - float *firstz; + /* constructs channels for reading, allocates memory in channels */ + ExrHandle *handle= imb_exr_begin_read_mem(file, width, height); + if(handle) { + IMB_exr_read_channels(handle); + ibuf->userdata= handle; /* potential danger, the caller has to check for this! */ + return ibuf; + } + } + else { + FrameBuffer frameBuffer; + float *first; + int xstride = sizeof(float) * 4; + int ystride = - xstride*width; + + imb_addrectfloatImBuf(ibuf); + + /* inverse correct first pixel for datawindow coordinates (- dw.min.y because of y flip) */ + first= ibuf->rect_float - 4*(dw.min.x - dw.min.y*width); + /* but, since we read y-flipped (negative y stride) we move to last scanline */ + first+= 4*(height-1)*width; + + frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); + frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); + frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); + /* 1.0 is fill value */ + frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); + + if(exr_has_zbuffer(file)) + { + float *firstz; + + addzbuffloatImBuf(ibuf); + firstz= ibuf->zbuf_float - (dw.min.x - dw.min.y*width); + firstz+= (height-1)*width; + frameBuffer.insert ("Z", Slice (FLOAT, (char *)firstz , sizeof(float), -width*sizeof(float))); + } - addzbuffloatImBuf(ibuf); - firstz= ibuf->zbuf_float - (dw.min.x - dw.min.y*width); - if(!flipped) firstz+= (height-1)*width; - frameBuffer.insert ("Z", Slice (FLOAT, (char *)firstz , sizeof(float), -width*sizeof(float))); + file->setFrameBuffer (frameBuffer); + file->readPixels (dw.min.y, dw.max.y); + + IMB_rect_from_float(ibuf); } - - file->setFrameBuffer (frameBuffer); - file->readPixels (dw.min.y, dw.max.y); - - IMB_rect_from_float(ibuf); } + + delete file; } - delete file; - return(ibuf); } diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index ff71aab5f3c..feceb227e4b 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -32,28 +32,41 @@ /* experiment with more advanced exr api */ +/* Note: as for now openexr only supports 32 chars in channel names. + This api also supports max 8 channels per pass now. easy to fix! */ +#define EXR_LAY_MAXNAME 19 +#define EXR_PASS_MAXNAME 11 +#define EXR_TOT_MAXNAME 32 +#define EXR_PASS_MAXCHAN 8 + + #ifdef WITH_OPENEXR void * IMB_exr_get_handle (void); -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame); +void IMB_exr_add_channel (void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect); int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height); void IMB_exr_begin_write (void *handle, char *filename, int width, int height); void IMB_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley); -void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect); +void IMB_exr_set_channel (void *handle, char *layname, char *passname, int xstride, int ystride, float *rect); void IMB_exr_read_channels (void *handle); void IMB_exr_write_channels (void *handle); void IMB_exrtile_write_channels (void *handle, int partx, int party); +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, char *str), + void (*addpass)(void *base, void *lay, char *str, float *rect, int totchan, char *chan_id)); + void IMB_exr_close (void *handle); + #else /* ugly... but we only use it on pipeline.c, render module, now */ void * IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame) {} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) {} int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height) {return 0;} void IMB_exr_begin_write (void *handle, char *filename, int width, int height) {} @@ -65,6 +78,10 @@ void IMB_exr_read_channels (void *handle) {} void IMB_exr_write_channels (void *handle) {} void IMB_exrtile_write_channels (void *handle, int partx, int party) {} +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, char *str), + void (*addpass)(void *base, void *lay, char *str, float *rect, int totchan, char *chan_id)) {} + void IMB_exr_close (void *handle) {} #endif diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 45ef191277b..bfa6200d23b 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -270,7 +270,7 @@ struct ImBuf *IMB_loadiffname(char *naam, int flags) { ibuf= IMB_loadifffile(file, flags); - if (ibuf == 0) { + if (ibuf == NULL) { if (read(file, buf, 4) != 4) buf[0] = 0; if ((BIG_LONG(buf[0]) & 0xfffffff0) == 0xffd8ffe0) ibuf = imb_ibJpegImageFromFilename(naam, flags); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 41183ce91da..429fcb109ea 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -332,6 +332,8 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &width, &height); if (width == 0 || height == 0) return; + if (sbuf && sbuf->channels!=4) return; + if (dbuf->channels!=4) return; do_char = (sbuf && sbuf->rect && dbuf->rect); do_float = (sbuf && sbuf->rect_float && dbuf->rect_float); diff --git a/source/blender/include/BIF_butspace.h b/source/blender/include/BIF_butspace.h index f5ae79fcd80..f87e9797cb3 100644 --- a/source/blender/include/BIF_butspace.h +++ b/source/blender/include/BIF_butspace.h @@ -42,6 +42,8 @@ struct ID; extern void do_butspace(unsigned short event); extern void redraw_test_buttons(struct Object *new); +extern char *image_type_pup(void); + /* buttons_editing.c */ extern void validate_editbonebutton_cb(void *bonev, void *namev); diff --git a/source/blender/include/BIF_drawimage.h b/source/blender/include/BIF_drawimage.h index a3b12b7bafd..5c289cfc2a4 100644 --- a/source/blender/include/BIF_drawimage.h +++ b/source/blender/include/BIF_drawimage.h @@ -36,6 +36,9 @@ struct ScrArea; struct SpaceImage; struct Render; +struct Image; +struct ImBuf; +struct uiBlock; void do_imagebuts(unsigned short event); void calc_image_view(struct SpaceImage *sima, char mode); @@ -51,8 +54,15 @@ void uvco_to_areaco_noclip(float *vec, int *mval); void what_image(struct SpaceImage *sima); void image_preview_event(int event); +void image_info(struct Image *ima, struct ImBuf *ibuf, char *str); +void imagespace_composite_flipbook(struct ScrArea *sa); + void imagewindow_render_callbacks(struct Render *re); void imagewindow_toggle_render(void); +void imagewindow_swap_render_rects(void); +void imagewin_store_spare(void); + +void image_editvertex_buts(struct uiBlock *block); #endif diff --git a/source/blender/include/BIF_editsima.h b/source/blender/include/BIF_editsima.h index 46444c88ae3..6a67ebc7009 100644 --- a/source/blender/include/BIF_editsima.h +++ b/source/blender/include/BIF_editsima.h @@ -76,7 +76,10 @@ void new_image_sima(void); void reload_image_sima(void); void save_image_sima(void); void save_as_image_sima(void); +void save_image_sequence_sima(void); void replace_image_sima(short imageselect); void open_image_sima(short imageselect); void pack_image_sima(void); +/* checks images for forced updates on frame change */ +void BIF_image_update_frame(void); diff --git a/source/blender/include/BIF_renderwin.h b/source/blender/include/BIF_renderwin.h index a997efb336d..789c3661db7 100644 --- a/source/blender/include/BIF_renderwin.h +++ b/source/blender/include/BIF_renderwin.h @@ -50,6 +50,7 @@ void BIF_renderwin_set_custom_cursor(unsigned char mask[16][2], unsigned char bi void BIF_redraw_render_rect(void); void BIF_swap_render_rects(void); +void BIF_store_spare(void); void BIF_toggle_render_display(void); void BIF_init_render_callbacks(struct Render *re, int do_display); diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index 7bf0814b82e..1e84dba39cb 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -64,6 +64,7 @@ struct SpaceOops; #define IMAGE_HANDLER_PAINT 31 #define IMAGE_HANDLER_CURVES 32 #define IMAGE_HANDLER_PREVIEW 33 +#define IMAGE_HANDLER_GAME_PROPERTIES 34 /* action handler codes */ #define ACTION_HANDLER_PROPERTIES 40 diff --git a/source/blender/include/BIF_writeimage.h b/source/blender/include/BIF_writeimage.h index 002d382be5b..70978a033c2 100644 --- a/source/blender/include/BIF_writeimage.h +++ b/source/blender/include/BIF_writeimage.h @@ -37,7 +37,7 @@ struct ImBuf; struct EnvMap; void BIF_save_rendered_image(char *name); -void BIF_save_rendered_image_fs(int zbuf); +void BIF_save_rendered_image_fs(void); void BIF_save_envmap(struct EnvMap *env, char *str); void save_image_filesel_str(char *str); diff --git a/source/blender/include/BSE_filesel.h b/source/blender/include/BSE_filesel.h index 29f9c52f79f..6934899062e 100644 --- a/source/blender/include/BSE_filesel.h +++ b/source/blender/include/BSE_filesel.h @@ -40,7 +40,6 @@ struct ID; struct ScrArea; struct BWinEvent; -void clear_global_filesel_vars(void); void filesel_statistics(struct SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen); void test_flags_file(struct SpaceFile *sfile); void sort_filelist(struct SpaceFile *sfile); @@ -49,9 +48,16 @@ void freefilelist(struct SpaceFile *sfile); void parent(struct SpaceFile *sfile); void swapselect_file(struct SpaceFile *sfile); void drawfilespace(struct ScrArea *sa, void *spacedata); + void activate_fileselect(int type, char *title, char *file, void (*func)(char *)); +void activate_fileselect_menu(int type, char *title, char *file, char *pupmenu, short *menup, void (*func)(char *)); +void activate_fileselect_args(int type, char *title, char *file, void (*func)(char *, void *, void *), void *arg1, void *arg2); + void activate_imageselect(int type, char *title, char *file, void (*func)(char *)); + void activate_databrowse(struct ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short)); +void activate_databrowse_args(struct ID *id, int idcode, int fromcode, short *menup, void (*func)(char *, void *, void *), void *arg1, void *arg2); + void filesel_prevspace(void); void free_filesel_spec(char *dir); void winqreadfilespace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); diff --git a/source/blender/include/BSE_node.h b/source/blender/include/BSE_node.h index 626c9e75cbc..bbe79c1e8ff 100644 --- a/source/blender/include/BSE_node.h +++ b/source/blender/include/BSE_node.h @@ -44,6 +44,8 @@ struct bNodeTree; struct Material; struct ID; struct Scene; +struct Image; +struct ImageUser; /* ************* API for editnode.c *********** */ @@ -82,6 +84,12 @@ void node_adduplicate(struct SpaceNode *snode); void snode_autoconnect(struct SpaceNode *snode, struct bNode *node_to, int flag); void node_select_linked(struct SpaceNode *snode, int out); +struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree); + +void imagepaint_composite_tags(struct bNodeTree *ntree, struct Image *image, struct ImageUser *iuser); + + + /* ************* drawnode.c *************** */ struct SpaceNode; struct bNodeLink; diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index fee04ac50a8..aaad17453ef 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -44,8 +44,7 @@ /* max length material array, 16 because of bits in matfrom */ #define MAXPICKBUF 10000 #define MAXSEQ 32 -/* in Image struct */ -#define MAXMIPMAP 10 + /* in buttons.c */ #define MAX_EFFECT 20 @@ -326,6 +325,13 @@ #define B_SIMABRUSHCHANGE 377 #define B_SIMABTEXBROWSE 378 #define B_SIMABTEXDELETE 379 +#define B_SIMARELOAD 380 +#define B_SIMANAME 381 +#define B_SIMAMULTI 382 +#define B_TRANS_IMAGE 383 +#define B_SIMA_REPACK 384 +#define B_SIMA_PLAY 385 +#define B_SIMA_RECORD 386 /* BUTS: 400 */ #define B_BUTSHOME 401 diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index bd0b2adaa31..75bc8ff6ed3 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -41,6 +41,8 @@ struct ColorBand; struct uiBlock; struct rctf; struct CurveMap; +struct ImageUser; +struct RenderResult; /* buts->scaflag */ #define BUTS_SENS_SEL 1 @@ -115,6 +117,10 @@ extern void radio_panels(void); extern void do_radiobuts(unsigned short event); extern void texture_panels(void); extern void do_texbuts(unsigned short event); +void uiblock_image_panel(struct uiBlock *block, struct Image **ima_pp, struct ImageUser *iuser, + short redraw, short imagechanged); +void uiblock_layer_pass_buttons(struct uiBlock *block, struct RenderResult *rr, + struct ImageUser *iuser, int event, int x, int y, int w); /* logic */ extern void do_logic_buts(unsigned short event); @@ -151,18 +157,11 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la /* *********************** */ #define B_VIEWBUTS 1100 -#define B_LOADBGPIC 1001 -#define B_BLENDBGPIC 1002 -#define B_BGPICBROWSE 1003 -#define B_BGPICTEX 1004 -#define B_BGPICCLEAR 1005 -#define B_BGPICTEXCLEAR 1006 - #define B_OBJECTPANELROT 1007 -#define B_OBJECTPANELMEDIAN 1008 +#define B_OBJECTPANELMEDIAN 1008 #define B_ARMATUREPANEL1 1009 #define B_ARMATUREPANEL2 1010 -#define B_OBJECTPANELPARENT 1011 +#define B_OBJECTPANELPARENT 1011 #define B_OBJECTPANEL 1012 #define B_ARMATUREPANEL3 1013 #define B_OBJECTPANELSCALE 1014 @@ -213,13 +212,12 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_TEXTYPE 1301 #define B_DEFTEXVAR 1302 -#define B_LOADTEXIMA 1303 + #define B_NAMEIMA 1304 #define B_TEXCHANNEL 1305 #define B_TEXREDR_PRV 1306 -#define B_TEXIMABROWSE 1307 -#define B_IMAPTEST 1308 -#define B_RELOADIMA 1309 +#define B_IMAGECHANGED 1307 + #define B_LOADPLUGIN 1310 #define B_NAMEPLUGIN 1311 #define B_COLORBAND 1312 @@ -233,20 +231,18 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_LOADTEXIMA1 1320 #define B_TEXPRV 1321 + #define B_PLUGBUT 1325 /* B_PLUGBUT reserves 24 buttons at least! */ #define B_ENV_MAKE 1350 #define B_ENV_FREE 1351 -#define B_ENV_DELETE 1352 +#define B_ENV_DELETE 1352 #define B_ENV_SAVE 1353 #define B_ENV_OB 1354 -#define B_PACKIMA 1355 -#define B_TEXSETFRAMES 1356 +#define B_ENV_FREE_ALL 1357 -#define B_ENV_FREE_ALL 1357 -#define B_UNLINKIMA 1358 /* **************** animbuts = object buttons ******* */ #define B_ANIMBUTS 1500 diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index deabcee590a..d99e19ce456 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -39,6 +39,7 @@ struct PackedFile; struct anim; struct ImBuf; +struct RenderResult; typedef struct PreviewImage { unsigned int w; @@ -46,23 +47,43 @@ typedef struct PreviewImage { unsigned int * rect; } PreviewImage; +/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ +/* should be used in conjunction with an ID * to Image. */ +typedef struct ImageUser { + int framenr; /* movies, sequences: current to display */ + int frames; /* total amount of frames to use */ + int offset, sfra; /* offset within movie, start frame in global time */ + short fie_ima, cycl; /* fields/image in movie, cyclic flag */ + short flag, ok; + + short multi_index, layer, pass; /* listbase indices, for menu browsing or retrieve buffer */ + short menunr; /* localized menu entry, for handling browse event */ +} ImageUser; + +/* iuser->flag */ +#define IMA_ANIM_ALWAYS 1 +#define IMA_ANIM_REFRESHED 2 + typedef struct Image { ID id; - char name[160]; + char name[240]; + ListBase ibufs; /* not written in file */ + + /* sources from: */ struct anim *anim; - struct ImBuf *ibuf; - struct ImBuf *mipmap[10]; + struct RenderResult *rr; short ok, flag; + short source, type, pad, pad1; int lastframe; /* texture page */ short tpageflag, totbind; short xrep, yrep; short twsta, twend; - unsigned int bindcode; + unsigned int bindcode; /* only for current image... */ unsigned int *repbind; /* for repeat of parts of images */ struct PackedFile * packedfile; @@ -71,25 +92,25 @@ typedef struct Image { float lastupdate; int lastused; short animspeed; - short reserved1; - int reserved2; + + short gen_x, gen_y, gen_type; /* for generated images */ + /*#ifdef WITH_VERSE*/ void *vnode; /* pointer at verse bitmap node */ /*#endif*/ } Image; -/* in Image struct */ -#define MAXMIPMAP 10 /* **************** IMAGE ********************* */ /* flag */ -#define IMA_HALVE 1 -#define IMA_BW 2 -#define IMA_FROMANIM 4 -#define IMA_USED 8 +#define IMA_FIELDS 1 +#define IMA_STD_FIELD 2 + #define IMA_REFLECT 16 #define IMA_NOCOLLECT 32 +#define IMA_ANTIALI 64 + /* tpageflag */ #define IMA_TILES 1 @@ -97,5 +118,7 @@ typedef struct Image { #define IMA_COLCYCLE 4 /* Depreciated */ #define IMA_MIPMAP_COMPLETE 8 /* all mipmap levels in OpenGL texture set? */ +/* ima->type and ima->source moved to BKE_image.h, for API */ + #endif diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index efc812af092..5e899dce0f6 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -182,6 +182,7 @@ typedef struct bNodeTree { /* data structs, for node->storage */ +/* this one has been replaced with ImageUser, keep it for do_versions() */ typedef struct NodeImageAnim { int frames, sfra, nr; char cyclic, movie; diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h index 7c4dc58006a..a0fdd892106 100644 --- a/source/blender/makesdna/DNA_packedFile_types.h +++ b/source/blender/makesdna/DNA_packedFile_types.h @@ -55,6 +55,7 @@ enum PF_FileStatus PF_USE_LOCAL, PF_USE_ORIGINAL, PF_KEEP, + PF_REMOVE, PF_NOOP, PF_ASK diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 87ff72f7025..8f3ee4e0e3f 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -593,15 +593,16 @@ typedef struct Scene { #define R_AVIJPEG 16 #define R_PNG 17 #define R_AVICODEC 18 -#define R_QUICKTIME 19 +#define R_QUICKTIME 19 #define R_BMP 20 #define R_RADHDR 21 #define R_TIFF 22 #define R_OPENEXR 23 #define R_FFMPEG 24 #define R_FRAMESERVER 25 -#define R_CINEON 26 -#define R_DPX 27 +#define R_CINEON 26 +#define R_DPX 27 +#define R_MULTILAYER 28 /* subimtype, flag options for imtype */ #define R_OPENEXR_HALF 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 210ecc20119..1f5391d59b1 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -36,7 +36,8 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" -#include "DNA_oops_types.h" /* for TreeStoreElem */ +#include "DNA_oops_types.h" /* for TreeStoreElem */ +#include "DNA_image_types.h" /* ImageUser */ /* Hum ... Not really nice... but needed for spacebuts. */ #include "DNA_view2d_types.h" @@ -163,31 +164,27 @@ typedef struct SpaceFile { struct direntry *filelist; int totfile; + char title[24]; char dir[160]; char file[80]; + short type, ofs, flag, sort; short maxnamelen, collums; struct BlendHandle *libfiledata; - short retval, ipotype; - short menu, act; - - /* changed type for compiling */ - /* void (*returnfunc)(short); ? used with char* ....*/ - /** - * @attention Called in filesel.c: - * @attention returnfunc(this->retval) : short - * @attention returnfunc(name) : char* - * @attention Other uses are limited to testing against - * @attention the value. How do we resolve this? Two args? - * @attention For now, keep the char*, as it seems stable. - * @attention Be warned that strange behaviour _has_ been spotted! - */ - void (*returnfunc)(char*); - - short *menup; + unsigned short retval; /* event */ + short menu, act, ipotype; + + /* one day we'll add unions to dna */ + void (*returnfunc)(char *); + void (*returnfunc_event)(unsigned short); + void (*returnfunc_args)(char *, void *, void *); + + void *arg1, *arg2; + short *menup; /* pointer to menu result or ID browsing */ + char *pupmenu; /* optional menu in header */ } SpaceFile; typedef struct SpaceOops { @@ -228,18 +225,21 @@ typedef struct SpaceImage { View2D v2d; struct Image *image; + struct ImageUser iuser; + struct CurveMapping *cumap; short mode, menunr; short imanr, curtile; int flag; - short pad1, lock; - - float zoom, pad2; + short imtypenr, lock; + short showspare, pad2; + float zoom; - float xof, yof; /* user defined offset, image is centered */ + float xof, yof; /* user defined offset, image is centered */ + float centx, centy; /* storage for offset while render drawing */ - float centx, centy; /* storage for offset while render drawing */ - char *info_str; /* info string for render */ + char *info_str, *info_spare; /* info string for render */ + struct ImBuf *spare; } SpaceImage; typedef struct SpaceNla{ @@ -429,9 +429,11 @@ typedef struct SpaceImaSel { /* sbuts->flag */ #define SB_PRV_OSA 1 -/* these values need to be hardcoded in blender.h SpaceFile: struct dna does not recognize defines */ +/* these values need to be hardcoded in structs, dna does not recognize defines */ +/* also defined in BKE */ #define FILE_MAXDIR 160 #define FILE_MAXFILE 80 +#define FILE_MAX 240 /* filesel types */ #define FILE_UNIX 8 @@ -589,7 +591,8 @@ typedef struct SpaceImaSel { #define TIME_ALL_ANIM_WIN 4 #define TIME_ALL_BUTS_WIN 8 #define TIME_WITH_SEQ_AUDIO 16 -#define TIME_SEQ 32 +#define TIME_SEQ 32 +#define TIME_ALL_IMAGE_WIN 64 /* sseq->mainb */ #define SEQ_DRAW_SEQUENCE 0 diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 01de2196f8c..eae2a07ec6e 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -35,6 +35,7 @@ #define DNA_TEXTURE_TYPES_H #include "DNA_ID.h" +#include "DNA_image_types.h" struct Ipo; struct PluginTex; @@ -43,6 +44,7 @@ struct EnvMap; struct Object; struct Tex; struct Image; +struct ImBuf; typedef struct MTex { @@ -112,7 +114,7 @@ typedef struct ColorBand { typedef struct EnvMap { struct Object *object; struct Image *ima; /* type ENV_LOAD */ - struct Image *cube[6]; /* these images are dynamic, not part of the main struct */ + struct ImBuf *cube[6]; /* these images are dynamic, not part of the main struct */ float imat[4][4]; float obimat[3][3]; short type, stype; @@ -152,19 +154,23 @@ typedef struct Tex { float cropxmin, cropymin, cropxmax, cropymax; short xrepeat, yrepeat; short extend; + + /* variables disabled, moved to struct iuser */ short fie_ima; int len; - float checkerdist, nabla; int frames, offset, sfra; + + float checkerdist, nabla; float norfac; + struct ImageUser iuser; + struct Ipo *ipo; struct Image *ima; struct PluginTex *plugin; struct ColorBand *coba; struct EnvMap *env; - int fradur[4][2]; } Tex; @@ -234,18 +240,18 @@ typedef struct TexMapping { #define TEX_INTERPOL 1 #define TEX_USEALPHA 2 #define TEX_MIPMAP 4 -#define TEX_FIELDS 8 #define TEX_IMAROT 16 #define TEX_CALCALPHA 32 -#define TEX_ANIMCYCLIC 64 -#define TEX_ANIM5 128 -#define TEX_ANTIALI 256 -#define TEX_ANTISCALE 512 -#define TEX_STD_FIELD 1024 #define TEX_NORMALMAP 2048 #define TEX_GAUSS_MIP 4096 -#define TEX_MORKPATCH 16384 +/* imaflag unused, only for version check */ +#define TEX_FIELDS_ 8 +#define TEX_ANIMCYCLIC_ 64 +#define TEX_ANIM5_ 128 +#define TEX_ANTIALI_ 256 +#define TEX_ANTISCALE_ 512 +#define TEX_STD_FIELD_ 1024 /* flag */ #define TEX_COLORBAND 1 diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 27ccc318067..451c9c231c2 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -54,17 +54,16 @@ struct RetopoViewData; #endif #include "DNA_listBase.h" +#include "DNA_image_types.h" /* The near/far thing is a Win EXCEPTION. Thus, leave near/far in the * code, and patch for windows. */ typedef struct BGpic { struct Image *ima; - struct ImBuf *ibuf; - struct Tex *tex; + struct ImageUser iuser; float xof, yof, size, zoom, blend; short xim, yim; - unsigned int *rect; } BGpic; typedef struct View3D { diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index ae51f85744e..c5e8fb27559 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -1534,6 +1534,7 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) PyObject *pyObjImage; BPy_Image *py_img; Image *image; + ImBuf *ibuf; float originX, originY; float zoomX = 1.0, zoomY = 1.0; int clipX = 0, clipY = 0, clipW = -1, clipH = -1; @@ -1559,14 +1560,15 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) /* fetch a C Image pointer from the passed-in Python object */ py_img = ( BPy_Image * ) pyObjImage; image = py_img->image; - - /* load the image data if necessary */ - if( !image->ibuf ) /* if no image data is available ... */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - if( !image->ibuf ) /* if failed to load the image */ + ibuf = BKE_image_get_ibuf( image, NULL ); + + if( !ibuf ) /* if failed to load the image */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't load image data in Blender" ); - + "couldn't load image data in Blender" ); + if( !ibuf->rect ) /* no float yet */ + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Image has no byte rect" ); + /* Update the time tag of the image */ tag_image_time(image); @@ -1575,12 +1577,12 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) * the clipping is just checked against the bounds of the image. * if clipW or clipH are less than zero then they include as much of * the image as they can. */ - clipX = EXPP_ClampInt( clipX, 0, image->ibuf->x ); - clipY = EXPP_ClampInt( clipY, 0, image->ibuf->y ); - if( ( clipW < 0 ) || ( clipW > ( image->ibuf->x - clipW ) ) ) - clipW = image->ibuf->x - clipX; - if( ( clipH < 0 ) || ( clipH > ( image->ibuf->y - clipH ) ) ) - clipH = image->ibuf->y - clipY; + clipX = EXPP_ClampInt( clipX, 0, ibuf->x ); + clipY = EXPP_ClampInt( clipY, 0, ibuf->y ); + if( ( clipW < 0 ) || ( clipW > ( ibuf->x - clipW ) ) ) + clipW = ibuf->x - clipX; + if( ( clipH < 0 ) || ( clipH > ( ibuf->y - clipH ) ) ) + clipH = ibuf->y - clipY; /* -- we are "Go" to Draw! -- */ @@ -1626,13 +1628,13 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) /* set the width of the image (ROW_LENGTH), and the offset to the * clip origin within the image in x (SKIP_PIXELS) and * y (SKIP_ROWS) */ - glPixelStorei( GL_UNPACK_ROW_LENGTH, image->ibuf->x ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, ibuf->x ); glPixelStorei( GL_UNPACK_SKIP_PIXELS, clipX ); glPixelStorei( GL_UNPACK_SKIP_ROWS, clipY ); /* draw the image */ glDrawPixels( clipW, clipH, GL_RGBA, GL_UNSIGNED_BYTE, - image->ibuf->rect ); + ibuf->rect ); /* restore the defaults for some parameters (we could also use a * glPushClientAttrib() and glPopClientAttrib() pair). */ diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index 9d9ac6c6184..75dae874dd7 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -232,12 +232,12 @@ static PyObject *M_Image_New( PyObject * self, PyObject * args) if (width > 5000 || height > 5000 || width < 1 || height < 1) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "Image width and height must be between 1 and 5000" ) ); - image = new_image(width, height, name, 0); + image = BKE_add_image_size(width, height, name, 0); if( !image ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject Image_Type" ) ); - /* reset usage count, since new_image() incremented it */ + /* reset usage count, since BKE_add_image_size() incremented it */ /* image->id.us--; */ /* Strange, new images have a user count of one???, otherwise it messes up */ @@ -354,14 +354,13 @@ static PyObject *M_Image_Load( PyObject * self, PyObject * args ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject Image_Type" ) ); - img_ptr = add_image( fname ); + img_ptr = BKE_add_image_file( fname ); if( !img_ptr ) return ( EXPP_ReturnPyObjError( PyExc_IOError, "couldn't load image" ) ); - /*reload the image buffers*/ - free_image_buffers(img_ptr); - img_ptr->ibuf = IMB_loadiffname(img_ptr->name , 0); + /* force a load the image buffers*/ + BKE_image_get_ibuf(img_ptr, NULL); image->image = img_ptr; @@ -380,7 +379,7 @@ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) { PyObject *attr; - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); char *pixel; /* image data */ int index; /* offset into image data */ int x = 0; @@ -391,20 +390,17 @@ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers" ); - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* loading didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - if( image->ibuf->type == 1 ) /* bitplane image */ + if( ibuf->type == 1 ) /* bitplane image */ return EXPP_ReturnPyObjError( PyExc_TypeError, "unsupported bitplane image format" ); - if( x > ( image->ibuf->x - 1 ) - || y > ( image->ibuf->y - 1 ) - || x < image->ibuf->xorig || y < image->ibuf->yorig ) + if( x > ( ibuf->x - 1 ) + || y > ( ibuf->y - 1 ) + || x < ibuf->xorig || y < ibuf->yorig ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "x or y is out of range" ); @@ -413,9 +409,9 @@ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) so we calc ourselves */ - index = ( x + y * image->ibuf->x ) * pixel_size; + index = ( x + y * ibuf->x ) * pixel_size; - pixel = ( char * ) image->ibuf->rect; + pixel = ( char * ) ibuf->rect; attr = Py_BuildValue( "[f,f,f,f]", ( ( float ) pixel[index] ) / 255.0, ( ( float ) pixel[index + 1] ) / 255.0, @@ -440,7 +436,7 @@ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) static PyObject *Image_getPixelI( BPy_Image * self, PyObject * args ) { PyObject *attr; - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); char *pixel; /* image data */ int index; /* offset into image data */ int x = 0; @@ -451,20 +447,17 @@ static PyObject *Image_getPixelI( BPy_Image * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers" ); - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - if( image->ibuf->type == 1 ) /* bitplane image */ + if( ibuf->type == 1 ) /* bitplane image */ return EXPP_ReturnPyObjError( PyExc_TypeError, "unsupported bitplane image format" ); - if( x > ( image->ibuf->x - 1 ) - || y > ( image->ibuf->y - 1 ) - || x < image->ibuf->xorig || y < image->ibuf->yorig ) + if( x > ( ibuf->x - 1 ) + || y > ( ibuf->y - 1 ) + || x < ibuf->xorig || y < ibuf->yorig ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "x or y is out of range" ); @@ -473,9 +466,9 @@ static PyObject *Image_getPixelI( BPy_Image * self, PyObject * args ) so we calc ourselves */ - index = ( x + y * image->ibuf->x ) * pixel_size; + index = ( x + y * ibuf->x ) * pixel_size; - pixel = ( char * ) image->ibuf->rect; + pixel = ( char * ) ibuf->rect; attr = Py_BuildValue( "[i,i,i,i]", pixel[index], pixel[index + 1], @@ -493,7 +486,7 @@ static PyObject *Image_getPixelI( BPy_Image * self, PyObject * args ) static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) { - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); char *pixel; /* image data */ int index; /* offset into image data */ int x = 0; @@ -507,20 +500,17 @@ static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers and an array of 4 floats" ); - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - if( image->ibuf->type == 1 ) /* bitplane image */ + if( ibuf->type == 1 ) /* bitplane image */ return EXPP_ReturnPyObjError( PyExc_TypeError, "unsupported bitplane image format" ); - if( x > ( image->ibuf->x - 1 ) - || y > ( image->ibuf->y - 1 ) - || x < image->ibuf->xorig || y < image->ibuf->yorig ) + if( x > ( ibuf->x - 1 ) + || y > ( ibuf->y - 1 ) + || x < ibuf->xorig || y < ibuf->yorig ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "x or y is out of ruange" ); @@ -536,9 +526,9 @@ static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) so we calc ourselves */ - index = ( x + y * image->ibuf->x ) * pixel_size; + index = ( x + y * ibuf->x ) * pixel_size; - pixel = ( char * ) image->ibuf->rect; + pixel = ( char * ) ibuf->rect; pixel[index] = ( char ) ( p[0] * 255.0 ); pixel[index + 1] = ( char ) ( p[1] * 255.0 ); @@ -553,7 +543,7 @@ static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) static PyObject *Image_setPixelI( BPy_Image * self, PyObject * args ) { - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); char *pixel; /* image data */ int index; /* offset into image data */ int x = 0; @@ -567,20 +557,17 @@ static PyObject *Image_setPixelI( BPy_Image * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers and an list of 4 ints" ); - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - if( image->ibuf->type == 1 ) /* bitplane image */ + if( ibuf->type == 1 ) /* bitplane image */ return EXPP_ReturnPyObjError( PyExc_TypeError, "unsupported bitplane image format" ); - if( x > ( image->ibuf->x - 1 ) - || y > ( image->ibuf->y - 1 ) - || x < image->ibuf->xorig || y < image->ibuf->yorig ) + if( x > ( ibuf->x - 1 ) + || y > ( ibuf->y - 1 ) + || x < ibuf->xorig || y < ibuf->yorig ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "x or y is out of range" ); @@ -595,9 +582,9 @@ static PyObject *Image_setPixelI( BPy_Image * self, PyObject * args ) so we calc ourselves */ - index = ( x + y * image->ibuf->x ) * pixel_size; + index = ( x + y * ibuf->x ) * pixel_size; - pixel = ( char * ) image->ibuf->rect; + pixel = ( char * ) ibuf->rect; pixel[index] = ( char ) p[0]; pixel[index + 1] = ( char ) p[1]; @@ -612,17 +599,14 @@ static PyObject *Image_setPixelI( BPy_Image * self, PyObject * args ) static PyObject *Image_getMaxXY( BPy_Image * self ) { - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); PyObject *attr; - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - attr = Py_BuildValue( "[i,i]", image->ibuf->x, image->ibuf->y ); + attr = Py_BuildValue( "[i,i]", ibuf->x, ibuf->y ); if( attr ) return attr; @@ -636,18 +620,15 @@ static PyObject *Image_getMaxXY( BPy_Image * self ) static PyObject *Image_getMinXY( BPy_Image * self ) { - Image *image = self->image; + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); PyObject *attr; - if( !image->ibuf || !image->ibuf->rect ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf || !image->ibuf->rect ) /* didn't work */ + if( !ibuf || !ibuf->rect ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - attr = Py_BuildValue( "[i,i]", image->ibuf->xorig, - image->ibuf->yorig ); + attr = Py_BuildValue( "[i,i]", ibuf->xorig, + ibuf->yorig ); if( attr ) return attr; @@ -713,9 +694,9 @@ static PyObject *Image_makeCurrent( BPy_Image * self ) static PyObject *Image_save( BPy_Image * self ) { - if( !IMB_saveiff - ( self->image->ibuf, self->image->name, - self->image->ibuf->flags ) ) + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); + + if(!ibuf || !IMB_saveiff( ibuf, self->image->name, ibuf->flags ) ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "could not save image" ); @@ -849,18 +830,14 @@ static PyObject *Image_getFilename( BPy_Image * self ) static PyObject *Image_getSize( BPy_Image * self ) { - PyObject *attr; - Image *image = self->image; - + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); + PyObject *attr; - if( !image->ibuf ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf ) /* didn't work */ + if( !ibuf ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - attr = Py_BuildValue( "[hh]", image->ibuf->x, image->ibuf->y ); + attr = Py_BuildValue( "[hh]", ibuf->x, ibuf->y ); if( attr ) return attr; @@ -871,17 +848,14 @@ static PyObject *Image_getSize( BPy_Image * self ) static PyObject *Image_getDepth( BPy_Image * self ) { + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); PyObject *attr; - Image *image = self->image; - - if( !image->ibuf ) /* if no image data available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - if( !image->ibuf ) /* didn't work */ + if( !ibuf ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - attr = Py_BuildValue( "h", image->ibuf->depth ); + attr = Py_BuildValue( "h", ibuf->depth ); if( attr ) return attr; @@ -961,8 +935,8 @@ static PyObject *Image_reload( BPy_Image * self ) { Image *image = self->image; - free_image_buffers( image ); /* force read again */ - image->ok = 1; + BKE_image_signal(image, NULL, IMA_SIGNAL_RELOAD); + Py_RETURN_NONE; } @@ -982,29 +956,27 @@ static PyObject *Image_glLoad( BPy_Image * self ) unsigned int *bind = &image->bindcode; if( *bind == 0 ) { + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); - if( !image->ibuf ) /* if no image data is available */ - load_image( image, IB_rect, G.sce, G.scene->r.cfra ); /* loading it */ - - if( !image->ibuf ) /* didn't work */ + if( !ibuf ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); glGenTextures( 1, ( GLuint * ) bind ); glBindTexture( GL_TEXTURE_2D, *bind ); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, image->ibuf->x, - image->ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, - image->ibuf->rect ); + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, ibuf->x, + ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + ibuf->rect ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image->ibuf->x, - image->ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, - image->ibuf->rect ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, ibuf->x, + ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, + ibuf->rect ); /* raise the nocollect flag, image is not available for garbage collection @@ -1176,7 +1148,7 @@ static PyObject *Image_getAttr( BPy_Image * self, char *name ) else attr = EXPP_incr_ret_False(); } else if( strcmp( name, "has_data" ) == 0 ) { - if (self->image->ibuf) + if (self->image->ibufs.first) attr = EXPP_incr_ret_True(); else attr = EXPP_incr_ret_False(); diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 1e2588ea43e..42e8e1ca5f8 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -208,17 +208,13 @@ static const EXPP_map_pair tex_flag_map[] = { {NULL, 0} }; +/* NOTE: flags moved to image... */ static const EXPP_map_pair tex_imageflag_map[] = { {"InterPol", TEX_INTERPOL}, {"UseAlpha", TEX_USEALPHA}, {"MipMap", TEX_MIPMAP}, - {"Fields", TEX_FIELDS}, {"Rot90", TEX_IMAROT}, {"CalcAlpha", TEX_CALCALPHA}, - {"Cyclic", TEX_ANIMCYCLIC}, - {"Movie", TEX_ANIM5}, - {"StField", TEX_STD_FIELD}, - {"Anti", TEX_ANTIALI}, {"NormalMap", TEX_NORMALMAP}, {NULL, 0} }; @@ -397,6 +393,10 @@ GETFUNC( getName ); GETFUNC( getType ); GETFUNC( getSType ); GETFUNC( clearIpo ); +GETFUNC( getAnimMontage ); +GETFUNC( getAnimLength ); +SETFUNC( setAnimLength ); +SETFUNC( setAnimMontage ); #endif GETFUNC( oldgetSType ); @@ -405,8 +405,6 @@ GETFUNC( oldgetType ); GETFUNC(getProperties); GETFUNC( clearIpo ); GETFUNC( getAnimFrames ); -GETFUNC( getAnimLength ); -GETFUNC( getAnimMontage ); GETFUNC( getAnimOffset ); GETFUNC( getAnimStart ); GETFUNC( getBrightness ); @@ -455,8 +453,6 @@ OLDSETFUNC( setSType ); OLDSETFUNC( setType ); SETFUNC( setAnimFrames ); -SETFUNC( setAnimLength ); -SETFUNC( setAnimMontage ); SETFUNC( setAnimOffset ); SETFUNC( setAnimStart ); SETFUNC( setBrightness ); @@ -552,6 +548,7 @@ static PyGetSetDef BPy_Texture_getseters[] = { (getter)Texture_getAnimFrames, (setter)Texture_setAnimFrames, "Number of frames of a movie to use", NULL}, +#if 0 {"animLength", (getter)Texture_getAnimLength, (setter)Texture_setAnimLength, "Number of frames of a movie to use (0 for all)", @@ -560,6 +557,7 @@ static PyGetSetDef BPy_Texture_getseters[] = { (getter)Texture_getAnimMontage, (setter)Texture_setAnimMontage, "Montage mode, start frames and durations", NULL}, +#endif {"animOffset", (getter)Texture_getAnimOffset, (setter)Texture_setAnimOffset, "Offsets the number of the first movie frame to use", @@ -729,14 +727,16 @@ static PyGetSetDef BPy_Texture_getseters[] = { (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, "Mipmaps enabled ('ImageFlags')", (void *)TEX_MIPMAP}, - {"fields", - (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, - "Use of image's fields enabled ('ImageFlags')", - (void *)TEX_FIELDS}, {"rot90", (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, "X/Y flip for rendering enabled ('ImageFlags')", (void *)TEX_IMAROT}, +#if 0 + /* disabled, moved to image */ + {"fields", + (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, + "Use of image's fields enabled ('ImageFlags')", + (void *)TEX_FIELDS}, {"cyclic", (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, "Looping of animated frames enabled ('ImageFlags')", @@ -753,6 +753,7 @@ static PyGetSetDef BPy_Texture_getseters[] = { (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, "Standard field deinterlacing enabled ('ImageFlags')", (void *)TEX_STD_FIELD}, +#endif {"normalMap", (getter)Texture_getImageFlags, (setter)Texture_setImageFlags, "Use of image RGB values for normal mapping enabled ('ImageFlags')", @@ -1174,12 +1175,8 @@ static PyObject *M_Texture_ImageFlagsDict( void ) PyConstant_Insert(d, "INTERPOL", PyInt_FromLong(TEX_INTERPOL)); PyConstant_Insert(d, "USEALPHA", PyInt_FromLong(TEX_USEALPHA)); PyConstant_Insert(d, "MIPMAP", PyInt_FromLong(TEX_MIPMAP)); - PyConstant_Insert(d, "FIELDS", PyInt_FromLong(TEX_FIELDS)); PyConstant_Insert(d, "ROT90", PyInt_FromLong(TEX_IMAROT)); PyConstant_Insert(d, "CALCALPHA", PyInt_FromLong(TEX_CALCALPHA)); - PyConstant_Insert(d, "STFIELD", PyInt_FromLong(TEX_STD_FIELD)); - PyConstant_Insert(d, "MOVIE", PyInt_FromLong(TEX_ANIM5)); - PyConstant_Insert(d, "CYCLIC", PyInt_FromLong(TEX_ANIMCYCLIC)); PyConstant_Insert(d, "NORMALMAP", PyInt_FromLong(TEX_NORMALMAP)); } return ImageFlags; @@ -1422,11 +1419,13 @@ static PyObject *Texture_oldgetType( BPy_Texture * self ) static int Texture_setAnimFrames( BPy_Texture * self, PyObject * value ) { - return EXPP_setIValueClamped ( value, &self->texture->frames, + return EXPP_setIValueClamped ( value, &self->texture->iuser.frames, EXPP_TEX_ANIMFRAME_MIN, EXPP_TEX_ANIMFRAME_MAX, 'h' ); } +#if 0 +/* this was stupid to begin with! (ton) */ static int Texture_setAnimLength( BPy_Texture * self, PyObject * value ) { return EXPP_setIValueClamped ( value, &self->texture->len, @@ -1434,6 +1433,7 @@ static int Texture_setAnimLength( BPy_Texture * self, PyObject * value ) EXPP_TEX_ANIMLEN_MAX, 'h' ); } +/* this is too simple to keep supporting? disabled for time being (ton) */ static int Texture_setAnimMontage( BPy_Texture * self, PyObject * value ) { int fradur[4][2]; @@ -1458,17 +1458,18 @@ static int Texture_setAnimMontage( BPy_Texture * self, PyObject * value ) return 0; } +#endif static int Texture_setAnimOffset( BPy_Texture * self, PyObject * value ) { - return EXPP_setIValueClamped ( value, &self->texture->offset, + return EXPP_setIValueClamped ( value, &self->texture->iuser.offset, EXPP_TEX_ANIMOFFSET_MIN, EXPP_TEX_ANIMOFFSET_MAX, 'h' ); } static int Texture_setAnimStart( BPy_Texture * self, PyObject * value ) { - return EXPP_setIValueClamped ( value, &self->texture->sfra, + return EXPP_setIValueClamped ( value, &self->texture->iuser.sfra, EXPP_TEX_ANIMSTART_MIN, EXPP_TEX_ANIMSTART_MAX, 'h' ); } @@ -1610,13 +1611,8 @@ static int Texture_setImageFlags( BPy_Texture * self, PyObject * value, int bitmask = TEX_INTERPOL | TEX_USEALPHA | TEX_MIPMAP - | TEX_FIELDS | TEX_IMAROT | TEX_CALCALPHA - | TEX_ANIMCYCLIC - | TEX_ANIM5 - | TEX_ANTIALI - | TEX_STD_FIELD | TEX_NORMALMAP; if( !PyInt_CheckExact ( value ) ) { @@ -1631,13 +1627,6 @@ static int Texture_setImageFlags( BPy_Texture * self, PyObject * value, "invalid bit(s) set in mask" ); } - /* "mipmap" and "fields" can't be set at the same time */ - - if( ( param & TEX_MIPMAP ) && - ( param & TEX_FIELDS ) ) - return EXPP_ReturnIntError( PyExc_ValueError, - "image flags MIPMAP and FIELDS cannot be used together" ); - /* everything is OK; save the new flag setting */ self->texture->imaflag = param; @@ -2024,6 +2013,8 @@ static PyObject *Texture_getAnimFrames( BPy_Texture *self ) return attr; } +#if 0 +/* disabled. this option was too stupid! (ton) */ static PyObject *Texture_getAnimLength( BPy_Texture *self ) { PyObject *attr = PyInt_FromLong( self->texture->len ); @@ -2055,10 +2046,11 @@ static PyObject *Texture_getAnimMontage( BPy_Texture *self ) return attr; } +#endif static PyObject *Texture_getAnimOffset( BPy_Texture *self ) { - PyObject *attr = PyInt_FromLong( self->texture->offset ); + PyObject *attr = PyInt_FromLong( self->texture->iuser.offset ); if( !attr ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -2069,7 +2061,7 @@ static PyObject *Texture_getAnimOffset( BPy_Texture *self ) static PyObject *Texture_getAnimStart( BPy_Texture *self ) { - PyObject *attr = PyInt_FromLong( self->texture->sfra ); + PyObject *attr = PyInt_FromLong( self->texture->iuser.sfra ); if( !attr ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -2162,7 +2154,7 @@ static PyObject *Texture_getIntExtend( BPy_Texture * self ) static PyObject *Texture_getFieldsPerImage( BPy_Texture *self ) { - PyObject *attr = PyInt_FromLong( self->texture->fie_ima ); + PyObject *attr = PyInt_FromLong( self->texture->iuser.fie_ima ); if( !attr ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 8ef3c09ab00..2add056b4c8 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -42,6 +42,7 @@ struct View3D; /* keep me up here */ #include "BIF_drawscene.h" #include "BIF_renderwin.h" +#include "BIF_writeimage.h" #include "BLI_blenlib.h" @@ -108,7 +109,6 @@ enum rend_constants { #define EXPP_RENDER_ATTR_YF_GIMETHOD 34 #define EXPP_RENDER_ATTR_YF_GIQUALITY 35 -extern void save_rendered_image_cb_real(char *name, int zbuf, int confirm); /* Render doc strings */ static char M_Render_doc[] = "The Blender Render module"; @@ -420,8 +420,8 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args ) char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2]; char *name_str, filepath[FILE_MAXDIR+FILE_MAXFILE]; RenderResult *rr = NULL; - int zbuff = 0; - + int zbuff; + if( !PyArg_ParseTuple( args, "s|i", &name_str, &zbuff ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a filename (string) and optional int" ); @@ -431,7 +431,7 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args ) return EXPP_ReturnPyObjError( PyExc_ValueError, "full filename too long" ); - if (zbuff !=0 ) zbuff = 1; /*required 1/0 */ + if (zbuff !=0 ) zbuff = 1; /*required 1/0 */ /* removed! (ton) */ BLI_strncpy( filepath, self->renderContext->pic, sizeof(filepath) ); strcat(filepath, name_str); @@ -445,7 +445,7 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args ) BLI_splitdirstring(dir, str); strcpy(G.ima, dir); } - save_rendered_image_cb_real(filepath, zbuff,0); + BIF_save_rendered_image(filepath); } return EXPP_incr_ret(Py_None); } @@ -1902,11 +1902,9 @@ static int RenderData_setBackbufPath( BPy_RenderData *self, PyObject *value ) strcpy( self->renderContext->backbuf, name ); EXPP_allqueue( REDRAWBUTSSCENE, 0 ); - ima = add_image( name ); - if( ima ) { - free_image_buffers( ima ); - ima->ok = 1; - } + ima = BKE_add_image_file( name ); + if( ima ) + BKE_image_signal( ima, NULL, IMA_SIGNAL_RELOAD ); return 0; } diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 22b623816ab..72f266630c4 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -59,11 +59,14 @@ typedef struct Render Render; typedef struct RenderPass { struct RenderPass *next, *prev; int passtype, channels; + char name[16]; /* amount defined in openexr_multi.h */ + char chan_id[8]; /* amount defined in openexr_multi.h */ float *rect; } RenderPass; /* a renderlayer is a full image, but with all passes and samples */ /* size of the rects is defined in RenderResult */ +/* after render, the Combined pass is in rectf, for renderlayers read from files it is a real pass */ typedef struct RenderLayer { struct RenderLayer *next, *prev; @@ -75,7 +78,7 @@ typedef struct RenderLayer { struct Material *mat_override; struct Group *light_override; - float *rectf; /* 4 float, standard rgba buffer */ + float *rectf; /* 4 float, standard rgba buffer (read not above!) */ float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */ ListBase passes; @@ -111,6 +114,9 @@ typedef struct RenderResult { char exrfile[FILE_MAXDIR]; void *exrhandle; + /* for render results in Image, verify validity for sequences */ + int framenr; + } RenderResult; typedef struct RenderStats { @@ -134,6 +140,7 @@ void RE_FreeRender (struct Render *re); void RE_FreeAllRender (void); /* get results and statistics */ +void RE_FreeRenderResult(struct RenderResult *rr); struct RenderResult *RE_GetResult(struct Render *re); void RE_GetResultImage(struct Render *re, struct RenderResult *rr); struct RenderStats *RE_GetStats(struct Render *re); @@ -173,6 +180,8 @@ void RE_BlenderFrame(struct Render *re, struct Scene *scene, int frame); void RE_BlenderAnim(struct Render *re, struct Scene *scene, int sfra, int efra); void RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); +void RE_WriteRenderResult(RenderResult *rr, char *filename); +struct RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty); /* ancient stars function... go away! */ void RE_make_stars(struct Render *re, void (*initfunc)(void), diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 13ab6f7cd67..6c7d12c4c8c 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -51,6 +51,7 @@ struct ShadeInput; struct TexResult; struct Tex; struct Image; +struct ImBuf; /* texture.h */ @@ -65,8 +66,8 @@ void render_realtime_texture(struct ShadeInput *shi); /* imagetexture.h */ -int imagewraposa(struct Tex *tex, struct Image *ima, float *texvec, float *dxt, float *dyt, struct TexResult *texres); -int imagewrap(struct Tex *tex, struct Image *ima, float *texvec, struct TexResult *texres); +int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, float *texvec, float *dxt, float *dyt, struct TexResult *texres); +int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, float *texvec, struct TexResult *texres); void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float *result); #endif /* TEXTURE_EXT_H */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c6845754a7d..4f7420bacc2 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2989,7 +2989,7 @@ void RE_Database_Free(Render *re) if(re->scene) if(re->scene->r.scemode & R_FREE_IMAGE) if((re->r.scemode & R_PREVIEWBUTS)==0) - free_all_imagetextures(); + BKE_image_free_all_textures(); } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 1cb7eb98545..782308a65ec 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -66,45 +66,37 @@ /* ------------------------------------------------------------------------- */ -static void envmap_split_ima(EnvMap *env) +static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) { - ImBuf *ibuf; - Image *ima; -/* extern rectcpy(); */ int dx, part; BKE_free_envmapdata(env); - dx= env->ima->ibuf->y; + dx= ibuf->y; dx/= 2; - if(3*dx != env->ima->ibuf->x) { + if(3*dx != ibuf->x) { printf("Incorrect envmap size\n"); env->ok= 0; env->ima->ok= 0; } else { for(part=0; part<6; part++) { - ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0); - ima= MEM_callocN(sizeof(Image), "image"); - ima->ibuf= ibuf; - ima->ok= 1; - env->cube[part]= ima; + env->cube[part]= IMB_allocImBuf(dx, dx, 24, IB_rect, 0); } - IMB_rectcpy(env->cube[0]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[0], ibuf, 0, 0, 0, 0, dx, dx); - IMB_rectcpy(env->cube[1]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[1], ibuf, 0, 0, dx, 0, dx, dx); - IMB_rectcpy(env->cube[2]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[2], ibuf, 0, 0, 2*dx, 0, dx, dx); - IMB_rectcpy(env->cube[3]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[3], ibuf, 0, 0, 0, dx, dx, dx); - IMB_rectcpy(env->cube[4]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[4], ibuf, 0, 0, dx, dx, dx, dx); - IMB_rectcpy(env->cube[5]->ibuf, env->ima->ibuf, + IMB_rectcpy(env->cube[5], ibuf, 0, 0, 2*dx, dx, dx, dx); env->ok= ENV_OSA; } - printf("split\n"); } /* ------------------------------------------------------------------------- */ @@ -372,7 +364,6 @@ static void render_envmap(Render *re, EnvMap *env) /* only the cubemap and planar map is implemented */ Render *envre; ImBuf *ibuf; - Image *ima; float orthmat[4][4]; float oldviewinv[4][4], mat[4][4], tmat[4][4]; short part; @@ -431,11 +422,7 @@ static void render_envmap(Render *re, EnvMap *env) IMB_rect_from_float(ibuf); ibuf->rect_float= NULL; - ima= MEM_callocN(sizeof(Image), "image"); - - ima->ibuf= ibuf; - ima->ok= 1; - env->cube[part]= ima; + env->cube[part]= ibuf; } if(re->test_break()) break; @@ -629,13 +616,10 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe extern Render R; /* only in this call */ /* texvec should be the already reflected normal */ EnvMap *env; - Image *ima; + ImBuf *ibuf; float fac, vec[3], sco[3], dxts[3], dyts[3]; int face, face1; - if((R.r.mode & R_ENVMAP)==0) - return 0; - env= tex->env; if(env==NULL || (env->stype!=ENV_LOAD && env->object==NULL)) { texres->tin= 0.0; @@ -644,13 +628,9 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe if(env->stype==ENV_LOAD) { env->ima= tex->ima; if(env->ima && env->ima->ok) { - if(env->ima->ibuf==NULL) { - printf("load ibuf\n"); - BLI_lock_thread(LOCK_CUSTOM1); - if(env->ima->ibuf==NULL) ima_ibuf_is_nul(tex, env->ima); - if(env->ima->ok && env->ok==0) - envmap_split_ima(env); - BLI_unlock_thread(LOCK_CUSTOM1); + if(env->cube[0]==NULL) { + ImBuf *ibuf= BKE_image_get_ibuf(env->ima, NULL); + envmap_split_ima(env, ibuf); } } } @@ -667,7 +647,7 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe else MTC_Mat4Mul3Vecfl(R.viewinv, vec); face= envcube_isect(env, vec, sco); - ima= env->cube[face]; + ibuf= env->cube[face]; if(osatex) { if(env->object) { @@ -679,7 +659,7 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe MTC_Mat4Mul3Vecfl(R.viewinv, dyt); } set_dxtdyt(dxts, dyts, dxt, dyt, face); - imagewraposa(tex, ima, sco, dxts, dyts, texres); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres); /* edges? */ @@ -693,9 +673,9 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe VecSubf(vec, vec, dxt); if(face!=face1) { - ima= env->cube[face1]; + ibuf= env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, ima, sco, dxts, dyts, &texr1); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1); } else texr1.tr= texr1.tg= texr1.tb= texr1.ta= 0.0; @@ -706,9 +686,9 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe VecSubf(vec, vec, dyt); if(face!=face1) { - ima= env->cube[face1]; + ibuf= env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, ima, sco, dxts, dyts, &texr2); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2); } else texr2.tr= texr2.tg= texr2.tb= texr2.ta= 0.0; @@ -724,7 +704,7 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe } } else { - imagewrap(tex, ima, sco, texres); + imagewrap(tex, NULL, ibuf, sco, texres); } return 1; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index a876a09e0b7..39af0893f81 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -69,14 +69,26 @@ extern struct Render R; /* *********** IMAGEWRAPPING ****************** */ + /* x and y have to be checked for image size */ static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y) { int ofs = y * ibuf->x + x; if(ibuf->rect_float) { - float *fp= ibuf->rect_float + 4*ofs; - QUATCOPY(col, fp); + if(ibuf->channels==4) { + float *fp= ibuf->rect_float + 4*ofs; + QUATCOPY(col, fp); + } + else if(ibuf->channels==3) { + float *fp= ibuf->rect_float + 3*ofs; + VECCOPY(col, fp); + col[3]= 1.0f; + } + else { + float *fp= ibuf->rect_float + ofs; + col[0]= col[1]= col[2]= col[3]= *fp; + } } else { char *rect = (char *)( ibuf->rect+ ofs); @@ -88,156 +100,151 @@ static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y) } } -int imagewrap(Tex *tex, Image *ima, float *texvec, TexResult *texres) +int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, TexResult *texres) { - struct ImBuf *ibuf; float fx, fy, val1, val2, val3; - int x, y; - - texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0; + int x, y, retval; - if(ima==NULL || ima->ok== 0) { - if(texres->nor) return 3; - else return 1; - } + texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f; - if(ima->ibuf==NULL) { + /* we need to set retval OK, otherwise texture code generates normals itself... */ + retval= texres->nor?3:1; + + /* quick tests */ + if(ibuf==NULL && ima==NULL) + return retval; + if(ima) { + /* hack for icon render */ - if(R.r.scemode &R_NO_IMAGE_LOAD) - return 0; - if(ima->ibuf==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima); - BLI_unlock_thread(LOCK_CUSTOM1); - } + if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) + return retval; + + ibuf= BKE_image_get_ibuf(ima, &tex->iuser); } + if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + return retval; + + /* setup mapping */ + if(tex->imaflag & TEX_IMAROT) { + fy= texvec[0]; + fx= texvec[1]; + } + else { + fx= texvec[0]; + fy= texvec[1]; + } + + if(tex->extend == TEX_CHECKER) { + int xs, ys; + + xs= (int)floor(fx); + ys= (int)floor(fy); + fx-= xs; + fy-= ys; - if (ima->ok) { - ibuf = ima->ibuf; - - if(tex->imaflag & TEX_IMAROT) { - fy= texvec[0]; - fx= texvec[1]; + if( (tex->flag & TEX_CHECKER_ODD)==0) { + if((xs+ys) & 1);else return retval; } - else { - fx= texvec[0]; - fy= texvec[1]; + if( (tex->flag & TEX_CHECKER_EVEN)==0) { + if((xs+ys) & 1) return retval; } - - if(tex->extend == TEX_CHECKER) { - int xs, ys; - - xs= (int)floor(fx); - ys= (int)floor(fy); - fx-= xs; - fy-= ys; - - if( (tex->flag & TEX_CHECKER_ODD)==0) { - if((xs+ys) & 1);else return 0; - } - if( (tex->flag & TEX_CHECKER_EVEN)==0) { - if((xs+ys) & 1) return 0; - } - /* scale around center, (0.5, 0.5) */ - if(tex->checkerdist<1.0) { - fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5; - fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5; - } + /* scale around center, (0.5, 0.5) */ + if(tex->checkerdist<1.0) { + fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5; + fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5; } + } - x = (int)(fx*ibuf->x); - y = (int)(fy*ibuf->y); + x = (int)(fx*ibuf->x); + y = (int)(fy*ibuf->y); - if(tex->extend == TEX_CLIPCUBE) { - if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) { - return 0; - } + if(tex->extend == TEX_CLIPCUBE) { + if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) { + return retval; } - else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { - if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { - return 0; - } + } + else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { + if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { + return retval; } - else { - if(tex->extend==TEX_EXTEND) { - if(x>=ibuf->x) x = ibuf->x-1; - else if(x<0) x= 0; - } - else { - x= x % ibuf->x; - if(x<0) x+= ibuf->x; - } - if(tex->extend==TEX_EXTEND) { - if(y>=ibuf->y) y = ibuf->y-1; - else if(y<0) y= 0; - } - else { - y= y % ibuf->y; - if(y<0) y+= ibuf->y; - } + } + else { + if(tex->extend==TEX_EXTEND) { + if(x>=ibuf->x) x = ibuf->x-1; + else if(x<0) x= 0; } - - /* warning, no return before setting back! */ - if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect+= (ibuf->x*ibuf->y); + else { + x= x % ibuf->x; + if(x<0) x+= ibuf->x; } - - ibuf_get_color(&texres->tr, ibuf, x, y); - - if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect-= (ibuf->x*ibuf->y); + if(tex->extend==TEX_EXTEND) { + if(y>=ibuf->y) y = ibuf->y-1; + else if(y<0) y= 0; } - - if(tex->imaflag & TEX_USEALPHA) { - if(tex->imaflag & TEX_CALCALPHA); - else texres->talpha= 1; + else { + y= y % ibuf->y; + if(y<0) y+= ibuf->y; } - - if(texres->nor) { - if(tex->imaflag & TEX_NORMALMAP) { - // qdn: normal from color - texres->nor[0] = 2.f*(texres->tr - 0.5f); - texres->nor[1] = 2.f*(0.5f - texres->tg); - texres->nor[2] = 2.f*(texres->tb - 0.5f); - } - else { - /* bump: take three samples */ - val1= texres->tr+texres->tg+texres->tb; + } + + /* warning, no return before setting back! */ + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect+= (ibuf->x*ibuf->y); + } - if(xx-1) { - float col[4]; - ibuf_get_color(col, ibuf, x+1, y); - val2= (col[0]+col[1]+col[2]); - } - else val2= val1; + ibuf_get_color(&texres->tr, ibuf, x, y); + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect-= (ibuf->x*ibuf->y); + } - if(yy-1) { - float col[4]; - ibuf_get_color(col, ibuf, x, y+1); - val3= (col[0]+col[1]+col[2]); - } - else val3= val1; + if(tex->imaflag & TEX_USEALPHA) { + if(tex->imaflag & TEX_CALCALPHA); + else texres->talpha= 1; + } + + if(texres->nor) { + if(tex->imaflag & TEX_NORMALMAP) { + // qdn: normal from color + texres->nor[0] = 2.f*(texres->tr - 0.5f); + texres->nor[1] = 2.f*(0.5f - texres->tg); + texres->nor[2] = 2.f*(texres->tb - 0.5f); + } + else { + /* bump: take three samples */ + val1= texres->tr+texres->tg+texres->tb; - /* do not mix up x and y here! */ - texres->nor[0]= (val1-val2); - texres->nor[1]= (val1-val3); + if(xx-1) { + float col[4]; + ibuf_get_color(col, ibuf, x+1, y); + val2= (col[0]+col[1]+col[2]); } - } + else val2= val1; - BRICONTRGB; + if(yy-1) { + float col[4]; + ibuf_get_color(col, ibuf, x, y+1); + val3= (col[0]+col[1]+col[2]); + } + else val3= val1; - if(texres->talpha) texres->tin= texres->ta; - else if(tex->imaflag & TEX_CALCALPHA) { - texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb); + /* do not mix up x and y here! */ + texres->nor[0]= (val1-val2); + texres->nor[1]= (val1-val3); } - else texres->ta= texres->tin= 1.0; - - if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; + } + BRICONTRGB; + + if(texres->talpha) texres->tin= texres->ta; + else if(tex->imaflag & TEX_CALCALPHA) { + texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb); } + else texres->ta= texres->tin= 1.0; + + if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; - if(texres->nor) return 3; - else return 1; + return retval; } static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2) @@ -567,50 +574,27 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max } } -static void makemipmap(Tex *tex, Image *ima) -{ - struct ImBuf *ibuf, *nbuf; - int minsize, curmap=0; - - ibuf= ima->ibuf; - minsize= MIN2(ibuf->x, ibuf->y); - - while(minsize>10 && curmapmipmap)) { - if(tex->imaflag & TEX_GAUSS_MIP) { - nbuf= IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect, 0); - IMB_filterN(nbuf, ibuf); - ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(nbuf); - IMB_freeImBuf(nbuf); - } - else { - ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf); - } - ibuf= ima->mipmap[curmap]; - - curmap++; - minsize= MIN2(ibuf->x, ibuf->y); - } -} - void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *result) { TexResult texres; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - if(ima==NULL || ima->ok== 0 || ima->ibuf==NULL) { + if(ibuf==NULL) { + result[0]= result[1]= result[2]= result[3]= 0.0f; return; } - if( (R.flag & R_SEC_FIELD) && (ima->ibuf->flags & IB_fields) ) - ima->ibuf->rect+= (ima->ibuf->x*ima->ibuf->y); + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) + ibuf->rect+= (ibuf->x*ibuf->y); - boxsample(ima->ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1); + boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1); result[0]= texres.tr; result[1]= texres.tg; result[2]= texres.tb; result[3]= texres.ta; - if( (R.flag & R_SEC_FIELD) && (ima->ibuf->flags & IB_fields) ) - ima->ibuf->rect-= (ima->ibuf->x*ima->ibuf->y); + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) + ibuf->rect-= (ibuf->x*ibuf->y); } void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) @@ -630,354 +614,349 @@ void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *res -int imagewraposa(Tex *tex, Image *ima, float *texvec, float *dxt, float *dyt, TexResult *texres) +int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, float *dyt, TexResult *texres) { TexResult texr; - ImBuf *ibuf, *previbuf; float fx, fy, minx, maxx, miny, maxy, dx, dy; float maxd, pixsize, val1, val2, val3; int curmap, retval, imaprepeat, imapextend; - texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0; + texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f; /* we need to set retval OK, otherwise texture code generates normals itself... */ retval= texres->nor?3:1; - if(ima==NULL || ima->ok== 0) { + /* quick tests */ + if(ibuf==NULL && ima==NULL) return retval; + if(ima) { + + /* hack for icon render */ + if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) + return retval; + + ibuf= BKE_image_get_ibuf(ima, &tex->iuser); } + if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + return retval; - if(ima->ibuf==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima); - BLI_unlock_thread(LOCK_CUSTOM1); + /* mipmap test */ + if(tex->imaflag & TEX_MIPMAP) { + if(ibuf->flags & IB_fields); + else if(ibuf->mipmap[0]==NULL) { + BLI_lock_thread(LOCK_CUSTOM1); + + if(ibuf->mipmap[0]==NULL) + IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP); + + BLI_unlock_thread(LOCK_CUSTOM1); + } + } + + if(tex->imaflag & TEX_USEALPHA) { + if(tex->imaflag & TEX_CALCALPHA); + else texres->talpha= 1; } - if (ima->ok) { + texr.talpha= texres->talpha; - if(tex->imaflag & TEX_MIPMAP) { - if(ima->mipmap[0]==NULL) { - if(ima->mipmap[0]==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - if(ima->mipmap[0]==NULL) makemipmap(tex, ima); - BLI_unlock_thread(LOCK_CUSTOM1); - } - } - } + if(tex->imaflag & TEX_IMAROT) { + fy= texvec[0]; + fx= texvec[1]; + } + else { + fx= texvec[0]; + fy= texvec[1]; + } - ibuf = ima->ibuf; - - if(tex->imaflag & TEX_USEALPHA) { - if(tex->imaflag & TEX_CALCALPHA); - else texres->talpha= 1; - } - - texr.talpha= texres->talpha; - - if(tex->imaflag & TEX_IMAROT) { - fy= texvec[0]; - fx= texvec[1]; - } - else { - fx= texvec[0]; - fy= texvec[1]; - } - - if(ibuf->flags & IB_fields) { - if(R.r.mode & R_FIELDS) { /* field render */ - if(R.flag & R_SEC_FIELD) { /* correction for 2nd field */ - /* fac1= 0.5/( (float)ibuf->y ); */ - /* fy-= fac1; */ - } - else { /* first field */ - fy+= 0.5f/( (float)ibuf->y ); - } + if(ibuf->flags & IB_fields) { + if(R.r.mode & R_FIELDS) { /* field render */ + if(R.flag & R_SEC_FIELD) { /* correction for 2nd field */ + /* fac1= 0.5/( (float)ibuf->y ); */ + /* fy-= fac1; */ + } + else { /* first field */ + fy+= 0.5f/( (float)ibuf->y ); } } - - /* pixel coordinates */ + } + + /* pixel coordinates */ - minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] ); - maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] ); - miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] ); - maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] ); + minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] ); + maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] ); + miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] ); + maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] ); - /* tex_sharper has been removed */ - minx= tex->filtersize*(maxx-minx)/2.0f; - miny= tex->filtersize*(maxy-miny)/2.0f; - - if(tex->filtersize!=1.0f) { - dxt[0]*= tex->filtersize; - dxt[1]*= tex->filtersize; - dyt[0]*= tex->filtersize; - dyt[1]*= tex->filtersize; - } + /* tex_sharper has been removed */ + minx= tex->filtersize*(maxx-minx)/2.0f; + miny= tex->filtersize*(maxy-miny)/2.0f; + + if(tex->filtersize!=1.0f) { + dxt[0]*= tex->filtersize; + dxt[1]*= tex->filtersize; + dyt[0]*= tex->filtersize; + dyt[1]*= tex->filtersize; + } - if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny); - - if(minx>0.25) minx= 0.25; - else if(minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */ - if(miny>0.25) miny= 0.25; - else if(miny<0.00001f) miny= 0.00001f; + if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny); + + if(minx>0.25) minx= 0.25; + else if(minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */ + if(miny>0.25) miny= 0.25; + else if(miny<0.00001f) miny= 0.00001f; - - /* repeat and clip */ - imaprepeat= (tex->extend==TEX_REPEAT); - imapextend= (tex->extend==TEX_EXTEND); + + /* repeat and clip */ + imaprepeat= (tex->extend==TEX_REPEAT); + imapextend= (tex->extend==TEX_EXTEND); - if(tex->extend == TEX_CHECKER) { - int xs, ys, xs1, ys1, xs2, ys2, boundary; - - xs= (int)floor(fx); - ys= (int)floor(fy); + if(tex->extend == TEX_CHECKER) { + int xs, ys, xs1, ys1, xs2, ys2, boundary; + + xs= (int)floor(fx); + ys= (int)floor(fy); + + // both checkers available, no boundary exceptions, checkerdist will eat aliasing + if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) { + fx-= xs; + fy-= ys; + } + else { - // both checkers available, no boundary exceptions, checkerdist will eat aliasing - if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) { + xs1= (int)floor(fx-minx); + ys1= (int)floor(fy-miny); + xs2= (int)floor(fx+minx); + ys2= (int)floor(fy+miny); + boundary= (xs1!=xs2) || (ys1!=ys2); + + if(boundary==0) { + if( (tex->flag & TEX_CHECKER_ODD)==0) { + if((xs+ys) & 1); + else return retval; + } + if( (tex->flag & TEX_CHECKER_EVEN)==0) { + if((xs+ys) & 1) return retval; + } fx-= xs; fy-= ys; } else { - - xs1= (int)floor(fx-minx); - ys1= (int)floor(fy-miny); - xs2= (int)floor(fx+minx); - ys2= (int)floor(fy+miny); - boundary= (xs1!=xs2) || (ys1!=ys2); - - if(boundary==0) { - if( (tex->flag & TEX_CHECKER_ODD)==0) { - if((xs+ys) & 1); - else return retval; - } - if( (tex->flag & TEX_CHECKER_EVEN)==0) { - if((xs+ys) & 1) return retval; - } - fx-= xs; - fy-= ys; + if(tex->flag & TEX_CHECKER_ODD) { + if((xs1+ys) & 1) fx-= xs2; + else fx-= xs1; + + if((ys1+xs) & 1) fy-= ys2; + else fy-= ys1; } - else { - if(tex->flag & TEX_CHECKER_ODD) { - if((xs1+ys) & 1) fx-= xs2; - else fx-= xs1; - - if((ys1+xs) & 1) fy-= ys2; - else fy-= ys1; - } - if(tex->flag & TEX_CHECKER_EVEN) { - if((xs1+ys) & 1) fx-= xs1; - else fx-= xs2; - - if((ys1+xs) & 1) fy-= ys1; - else fy-= ys2; - } + if(tex->flag & TEX_CHECKER_EVEN) { + if((xs1+ys) & 1) fx-= xs1; + else fx-= xs2; + + if((ys1+xs) & 1) fy-= ys1; + else fy-= ys2; } } + } - /* scale around center, (0.5, 0.5) */ - if(tex->checkerdist<1.0) { - fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5; - fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5; - minx/= (1.0-tex->checkerdist); - miny/= (1.0-tex->checkerdist); - } + /* scale around center, (0.5, 0.5) */ + if(tex->checkerdist<1.0) { + fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5; + fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5; + minx/= (1.0-tex->checkerdist); + miny/= (1.0-tex->checkerdist); } + } - if(tex->extend == TEX_CLIPCUBE) { - if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) { - return retval; - } + if(tex->extend == TEX_CLIPCUBE) { + if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) { + return retval; } - else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { - if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) { - return retval; - } + } + else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { + if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) { + return retval; + } + } + else { + if(tex->extend==TEX_EXTEND) { + if(fx>1.0) fx = 1.0; + else if(fx<0.0) fx= 0.0; } else { - if(tex->extend==TEX_EXTEND) { - if(fx>1.0) fx = 1.0; - else if(fx<0.0) fx= 0.0; - } - else { - if(fx>1.0) fx -= (int)(fx); - else if(fx<0.0) fx+= 1-(int)(fx); - } - - if(tex->extend==TEX_EXTEND) { - if(fy>1.0) fy = 1.0; - else if(fy<0.0) fy= 0.0; - } - else { - if(fy>1.0) fy -= (int)(fy); - else if(fy<0.0) fy+= 1-(int)(fy); - } + if(fx>1.0) fx -= (int)(fx); + else if(fx<0.0) fx+= 1-(int)(fx); } - - /* warning no return! */ - if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect+= (ibuf->x*ibuf->y); + + if(tex->extend==TEX_EXTEND) { + if(fy>1.0) fy = 1.0; + else if(fy<0.0) fy= 0.0; } + else { + if(fy>1.0) fy -= (int)(fy); + else if(fy<0.0) fy+= 1-(int)(fy); + } + } - /* choice: */ - if(tex->imaflag & TEX_MIPMAP) { - float bumpscale; - - dx= minx; - dy= miny; - maxd= MAX2(dx, dy); - if(maxd>0.5) maxd= 0.5; + /* warning no return! */ + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect+= (ibuf->x*ibuf->y); + } - pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y); - - bumpscale= pixsize/maxd; - if(bumpscale>1.0f) bumpscale= 1.0f; - else bumpscale*=bumpscale; - - curmap= 0; - previbuf= ibuf; - while(curmapmipmap) && ima->mipmap[curmap]) { - if(maxd < pixsize) break; - previbuf= ibuf; - ibuf= ima->mipmap[curmap]; - pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* this used to be 1.0 */ - curmap++; - } + /* choice: */ + if(tex->imaflag & TEX_MIPMAP) { + ImBuf *previbuf, *curibuf; + float bumpscale; + + dx= minx; + dy= miny; + maxd= MAX2(dx, dy); + if(maxd>0.5) maxd= 0.5; - if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) { - /* sample at least 1 pixel */ - if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x; - if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y; - } + pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y); + + bumpscale= pixsize/maxd; + if(bumpscale>1.0f) bumpscale= 1.0f; + else bumpscale*=bumpscale; + + curmap= 0; + previbuf= curibuf= ibuf; + while(curmapmipmap[curmap]) { + if(maxd < pixsize) break; + previbuf= curibuf; + curibuf= ibuf->mipmap[curmap]; + pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y); + curmap++; + } + + if(previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) { + /* sample at least 1 pixel */ + if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x; + if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y; + } + + if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { + /* a bit extra filter */ + //minx*= 1.35f; + //miny*= 1.35f; - if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { - /* a bit extra filter */ - //minx*= 1.35f; - //miny*= 1.35f; + boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); + val1= texres->tr+texres->tg+texres->tb; + boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); + val2= texr.tr + texr.tg + texr.tb; + boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); + val3= texr.tr + texr.tg + texr.tb; + + /* don't switch x or y! */ + texres->nor[0]= (val1-val2); + texres->nor[1]= (val1-val3); + + if(previbuf!=curibuf) { /* interpolate */ - boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); - val1= texres->tr+texres->tg+texres->tb; - boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); - val2= texr.tr + texr.tg + texr.tb; - boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); - val3= texr.tr + texr.tg + texr.tb; - - /* don't switch x or y! */ - texres->nor[0]= (val1-val2); - texres->nor[1]= (val1-val3); + boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend); - if(previbuf!=ibuf) { /* interpolate */ - - boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend); - - /* calc rgb */ - dx= 2.0f*(pixsize-maxd)/pixsize; - if(dx>=1.0f) { - texres->ta= texr.ta; texres->tb= texr.tb; - texres->tg= texr.tg; texres->tr= texr.tr; - } - else { - dy= 1.0f-dx; - texres->tb= dy*texres->tb+ dx*texr.tb; - texres->tg= dy*texres->tg+ dx*texr.tg; - texres->tr= dy*texres->tr+ dx*texr.tr; - texres->ta= dy*texres->ta+ dx*texr.ta; - } - - val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb); - boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); - val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb); - boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); - val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb); - - texres->nor[0]= (val1-val2); /* vals have been interpolated above! */ - texres->nor[1]= (val1-val3); - - if(dx<1.0f) { - dy= 1.0f-dx; - texres->tb= dy*texres->tb+ dx*texr.tb; - texres->tg= dy*texres->tg+ dx*texr.tg; - texres->tr= dy*texres->tr+ dx*texr.tr; - texres->ta= dy*texres->ta+ dx*texr.ta; - } + /* calc rgb */ + dx= 2.0f*(pixsize-maxd)/pixsize; + if(dx>=1.0f) { + texres->ta= texr.ta; texres->tb= texr.tb; + texres->tg= texr.tg; texres->tr= texr.tr; } - texres->nor[0]*= bumpscale; - texres->nor[1]*= bumpscale; - } - else { - maxx= fx+minx; - minx= fx-minx; - maxy= fy+miny; - miny= fy-miny; - - boxsample(ibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend); - - if(previbuf!=ibuf) { /* interpolate */ - boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend); - - fx= 2.0f*(pixsize-maxd)/pixsize; - - if(fx>=1.0) { - texres->ta= texr.ta; texres->tb= texr.tb; - texres->tg= texr.tg; texres->tr= texr.tr; - } else { - fy= 1.0f-fx; - texres->tb= fy*texres->tb+ fx*texr.tb; - texres->tg= fy*texres->tg+ fx*texr.tg; - texres->tr= fy*texres->tr+ fx*texr.tr; - texres->ta= fy*texres->ta+ fx*texr.ta; - } + else { + dy= 1.0f-dx; + texres->tb= dy*texres->tb+ dx*texr.tb; + texres->tg= dy*texres->tg+ dx*texr.tg; + texres->tr= dy*texres->tr+ dx*texr.tr; + texres->ta= dy*texres->ta+ dx*texr.ta; + } + + val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb); + boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); + val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb); + boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); + val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb); + + texres->nor[0]= (val1-val2); /* vals have been interpolated above! */ + texres->nor[1]= (val1-val3); + + if(dx<1.0f) { + dy= 1.0f-dx; + texres->tb= dy*texres->tb+ dx*texr.tb; + texres->tg= dy*texres->tg+ dx*texr.tg; + texres->tr= dy*texres->tr+ dx*texr.tr; + texres->ta= dy*texres->ta+ dx*texr.ta; } } + texres->nor[0]*= bumpscale; + texres->nor[1]*= bumpscale; } else { - if((tex->imaflag & TEX_INTERPOL)) { - /* sample 1 pixel minimum */ - if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x; - if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y; - } + maxx= fx+minx; + minx= fx-minx; + maxy= fy+miny; + miny= fy-miny; + + boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend); - if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { + if(previbuf!=curibuf) { /* interpolate */ + boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend); - /* a bit extra filter */ - //minx*= 1.35f; - //miny*= 1.35f; + fx= 2.0f*(pixsize-maxd)/pixsize; - boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); - val1= texres->tr+texres->tg+texres->tb; - boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); - val2= texr.tr + texr.tg + texr.tb; - boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); - val3= texr.tr + texr.tg + texr.tb; - /* don't switch x or y! */ - texres->nor[0]= (val1-val2); - texres->nor[1]= (val1-val3); - } - else { - boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); + if(fx>=1.0) { + texres->ta= texr.ta; texres->tb= texr.tb; + texres->tg= texr.tg; texres->tr= texr.tr; + } else { + fy= 1.0f-fx; + texres->tb= fy*texres->tb+ fx*texr.tb; + texres->tg= fy*texres->tg+ fx*texr.tg; + texres->tr= fy*texres->tr+ fx*texr.tr; + texres->ta= fy*texres->ta+ fx*texr.ta; + } } } - - BRICONTRGB; - - if(tex->imaflag & TEX_CALCALPHA) { - texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb); + } + else { + if((tex->imaflag & TEX_INTERPOL)) { + /* sample 1 pixel minimum */ + if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x; + if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y; } - else texres->tin= texres->ta; - if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; - - if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect-= (ibuf->x*ibuf->y); + if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { + + boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); + val1= texres->tr+texres->tg+texres->tb; + boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); + val2= texr.tr + texr.tg + texr.tb; + boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); + val3= texr.tr + texr.tg + texr.tb; + /* don't switch x or y! */ + texres->nor[0]= (val1-val2); + texres->nor[1]= (val1-val3); } - - if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) { - // qdn: normal from color - texres->nor[0] = 2.f*(texres->tr - 0.5f); - texres->nor[1] = 2.f*(0.5f - texres->tg); - texres->nor[2] = 2.f*(texres->tb - 0.5f); + else { + boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); } } - else { - texres->tin= 0.0f; + + BRICONTRGB; + + if(tex->imaflag & TEX_CALCALPHA) { + texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb); + } + else texres->tin= texres->ta; + + if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect-= (ibuf->x*ibuf->y); + } + + if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) { + // qdn: normal from color + texres->nor[0] = 2.f*(texres->tr - 0.5f); + texres->nor[1] = 2.f*(0.5f - texres->tg); + texres->nor[2] = 2.f*(texres->tb - 0.5f); } return retval; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 3ce3b93f3a4..e62d66a354d 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -40,6 +40,7 @@ #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_main.h" #include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -162,7 +163,7 @@ static void stats_background(RenderStats *rs) } } -static void free_render_result(RenderResult *res) +void RE_FreeRenderResult(RenderResult *res) { if(res==NULL) return; @@ -197,7 +198,7 @@ static void free_render_result(RenderResult *res) static void push_render_result(Render *re) { /* officially pushed result should be NULL... error can happen with do_seq */ - free_render_result(re->pushedresult); + RE_FreeRenderResult(re->pushedresult); re->pushedresult= re->result; re->result= NULL; @@ -236,89 +237,157 @@ static void pop_render_result(Render *re) } } - free_render_result(re->pushedresult); + RE_FreeRenderResult(re->pushedresult); re->pushedresult= NULL; } } - +/* NOTE: OpenEXR only supports 32 chars for layer+pass names + In blender we now use max 10 chars for pass, max 20 for layer */ static char *get_pass_name(int passtype, int channel) { if(passtype == SCE_PASS_COMBINED) { + if(channel==-1) return "Combined"; if(channel==0) return "Combined.R"; - else if(channel==1) return "Combined.G"; - else if(channel==2) return "Combined.B"; - else return "Combined.A"; + if(channel==1) return "Combined.G"; + if(channel==2) return "Combined.B"; + return "Combined.A"; + } + if(passtype == SCE_PASS_Z) { + if(channel==-1) return "Depth"; + return "Depth.Z"; } - if(passtype == SCE_PASS_Z) - return "Z"; if(passtype == SCE_PASS_VECTOR) { + if(channel==-1) return "Vector"; if(channel==0) return "Vector.X"; - else if(channel==1) return "Vector.Y"; - else if(channel==2) return "Vector.Z"; - else return "Vector.W"; + if(channel==1) return "Vector.Y"; + if(channel==2) return "Vector.Z"; + return "Vector.W"; } if(passtype == SCE_PASS_NORMAL) { + if(channel==-1) return "Normal"; if(channel==0) return "Normal.X"; - else if(channel==1) return "Normal.Y"; - else return "Normal.Z"; + if(channel==1) return "Normal.Y"; + return "Normal.Z"; } if(passtype == SCE_PASS_UV) { - if(channel==0) return "Tex.U"; - else return "Tex.V"; + if(channel==-1) return "UV"; + if(channel==0) return "UV.U"; + if(channel==1) return "UV.V"; + return "UV.A"; } if(passtype == SCE_PASS_RGBA) { + if(channel==-1) return "Color"; if(channel==0) return "Color.R"; - else if(channel==1) return "Color.G"; - else if(channel==2) return "Color.B"; - else return "Color.A"; + if(channel==1) return "Color.G"; + if(channel==2) return "Color.B"; + return "Color.A"; } if(passtype == SCE_PASS_DIFFUSE) { + if(channel==-1) return "Diffuse"; if(channel==0) return "Diffuse.R"; - else if(channel==1) return "Diffuse.G"; - else return "Diffuse.B"; + if(channel==1) return "Diffuse.G"; + return "Diffuse.B"; } if(passtype == SCE_PASS_SPEC) { + if(channel==-1) return "Spec"; if(channel==0) return "Spec.R"; - else if(channel==1) return "Spec.G"; - else return "Spec.B"; + if(channel==1) return "Spec.G"; + return "Spec.B"; } if(passtype == SCE_PASS_SHADOW) { + if(channel==-1) return "Shadow"; if(channel==0) return "Shadow.R"; - else if(channel==1) return "Shadow.G"; - else return "Shadow.B"; + if(channel==1) return "Shadow.G"; + return "Shadow.B"; } if(passtype == SCE_PASS_AO) { + if(channel==-1) return "AO"; if(channel==0) return "AO.R"; - else if(channel==1) return "AO.G"; - else return "AO.B"; + if(channel==1) return "AO.G"; + return "AO.B"; } if(passtype == SCE_PASS_REFLECT) { + if(channel==-1) return "Reflect"; if(channel==0) return "Reflect.R"; - else if(channel==1) return "Reflect.G"; - else return "Reflect.B"; + if(channel==1) return "Reflect.G"; + return "Reflect.B"; } if(passtype == SCE_PASS_REFRACT) { + if(channel==-1) return "Refract"; if(channel==0) return "Refract.R"; - else if(channel==1) return "Refract.G"; - else return "Refract.B"; + if(channel==1) return "Refract.G"; + return "Refract.B"; } if(passtype == SCE_PASS_RADIO) { + if(channel==-1) return "Radio"; if(channel==0) return "Radio.R"; - else if(channel==1) return "Radio.G"; - else return "Radio.B"; + if(channel==1) return "Radio.G"; + return "Radio.B"; + } + if(passtype == SCE_PASS_INDEXOB) { + if(channel==-1) return "IndexOB"; + return "IndexOB.X"; } - if(passtype == SCE_PASS_INDEXOB) - return "IndexOB"; return "Unknown"; } +static int passtype_from_name(char *str) +{ + + if(strcmp(str, "Combined")==0) + return SCE_PASS_COMBINED; + + if(strcmp(str, "Depth")==0) + return SCE_PASS_Z; + + if(strcmp(str, "Vector")==0) + return SCE_PASS_VECTOR; + + if(strcmp(str, "Normal")==0) + return SCE_PASS_NORMAL; + + if(strcmp(str, "UV")==0) + return SCE_PASS_UV; + + if(strcmp(str, "Color")==0) + return SCE_PASS_RGBA; + + if(strcmp(str, "Diffuse")==0) + return SCE_PASS_DIFFUSE; + + if(strcmp(str, "Spec")==0) + return SCE_PASS_SPEC; + + if(strcmp(str, "Shadow")==0) + return SCE_PASS_SHADOW; + + if(strcmp(str, "AO")==0) + return SCE_PASS_AO; + + if(strcmp(str, "Reflect")==0) + return SCE_PASS_REFLECT; + + if(strcmp(str, "Refract")==0) + return SCE_PASS_REFRACT; + + if(strcmp(str, "Radio")==0) + return SCE_PASS_RADIO; + + if(strcmp(str, "IndexOB")==0) + return SCE_PASS_INDEXOB; + + return 0; +} + + + static void render_unique_exr_name(Render *re, char *str) { - char di[FILE_MAXDIR+FILE_MAXFILE], name[FILE_MAXFILE], fi[FILE_MAXFILE]; + char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE]; - BLI_strncpy(di, G.sce, FILE_MAXDIR+FILE_MAXFILE); + BLI_strncpy(di, G.sce, FILE_MAX); BLI_splitdirstring(di, fi); sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2); if(G.background) @@ -341,7 +410,7 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel if(rr->exrhandle) { int a; for(a=0; aexrhandle, rl->name, get_pass_name(passtype, a)); + IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); } else { if(passtype==SCE_PASS_VECTOR) { @@ -435,10 +504,10 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int rl->mat_override= srl->mat_override; if(rr->exrhandle) { - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R"); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G"); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B"); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A"); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } else rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba"); @@ -608,20 +677,142 @@ static void save_render_result_tile(Render *re, RenderPart *pa) } +/* for passes read from files, these have names stored */ +static char *make_pass_name(RenderPass *rpass, int chan) +{ + static char name[16]; + int len; + + BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); + len= strlen(name); + name[len]= '.'; + name[len+1]= rpass->chan_id[chan]; + name[len+2]= 0; + + return name; +} + +/* filename already made absolute */ +/* called from within UI, saves both rendered result as a file-read result */ +void RE_WriteRenderResult(RenderResult *rr, char *filename) +{ + RenderLayer *rl; + RenderPass *rpass; + void *exrhandle= IMB_exr_get_handle(); + + /* composite result */ + if(rr->rectf) { + IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf); + IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1); + IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2); + IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3); + } + + /* add layers/passes and assign channels */ + for(rl= rr->layers.first; rl; rl= rl->next) { + + /* combined */ + if(rl->rectf) { + int a, xstride= 4; + for(a=0; aname, get_pass_name(SCE_PASS_COMBINED, a), + xstride, xstride*rr->rectx, rl->rectf+a); + } + + /* passes are allocated in sync */ + for(rpass= rl->passes.first; rpass; rpass= rpass->next) { + int a, xstride= rpass->channels; + for(a=0; apasstype) + IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), + xstride, xstride*rr->rectx, rpass->rect+a); + else + IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), + xstride, xstride*rr->rectx, rpass->rect+a); + } + } + } + + IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty); + + IMB_exr_write_channels(exrhandle); + IMB_exr_close(exrhandle); +} + +/* callbacks for RE_MultilayerConvert */ +static void *ml_addlayer_cb(void *base, char *str) +{ + RenderResult *rr= base; + RenderLayer *rl; + + rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); + BLI_addtail(&rr->layers, rl); + + BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); + return rl; +} +static void ml_addpass_cb(void *base, void *lay, char *str, float *rect, int totchan, char *chan_id) +{ + RenderLayer *rl= lay; + RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass"); + int a; + + BLI_addtail(&rl->passes, rpass); + rpass->channels= totchan; + + rpass->passtype= passtype_from_name(str); + if(rpass->passtype==0) printf("unknown pass %s\n", str); + rl->passflag |= rpass->passtype; + + BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME); + /* channel id chars */ + for(a=0; achan_id[a]= chan_id[a]; + + rpass->rect= rect; +} + +/* from imbuf, if a handle was returned we convert this to render result */ +RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty) +{ + RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result"); + + rr->rectx= rectx; + rr->recty= recty; + + IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb); + + return rr; +} + +/* called in end of render, to add names to passes... for UI only */ +static void renderresult_add_names(RenderResult *rr) +{ + RenderLayer *rl; + RenderPass *rpass; + + for(rl= rr->layers.first; rl; rl= rl->next) + for(rpass= rl->passes.first; rpass; rpass= rpass->next) + strcpy(rpass->name, get_pass_name(rpass->passtype, -1)); +} + + +/* only for temp buffer files, makes exact copy of render result */ static void read_render_result(Render *re) { RenderLayer *rl; RenderPass *rpass; void *exrhandle= IMB_exr_get_handle(); int rectx, recty; - char str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); render_unique_exr_name(re, str); if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) { - printf("cannot read render result\n"); + IMB_exr_close(exrhandle); + printf("cannot read: %s\n", str); return; } @@ -649,6 +840,7 @@ static void read_render_result(Render *re) } IMB_exr_read_channels(exrhandle); + renderresult_add_names(re->result); } IMB_exr_close(exrhandle); @@ -787,8 +979,8 @@ void RE_FreeRender(Render *re) free_renderdata_tables(re); free_sample_tables(re); - free_render_result(re->result); - free_render_result(re->pushedresult); + RE_FreeRenderResult(re->result); + RE_FreeRenderResult(re->pushedresult); BLI_remlink(&RenderList, re); MEM_freeN(re); @@ -845,7 +1037,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect make_sample_tables(re); /* make empty render result, so display callbacks can initialize */ - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= MEM_callocN(sizeof(RenderResult), "new render result"); re->result->rectx= re->rectx; re->result->recty= re->recty; @@ -862,7 +1054,7 @@ void RE_SetDispRect (struct Render *re, rcti *disprect) re->recty= disprect->ymax-disprect->ymin; /* initialize render result */ - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); } @@ -981,7 +1173,7 @@ static void render_tile_processor(Render *re, int firsttile) /* hrmf... exception, this is used for preview render, re-entrant, so render result has to be re-used */ if(re->result==NULL || re->result->layers.first==NULL) { - if(re->result) free_render_result(re->result); + if(re->result) RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); } @@ -1010,7 +1202,7 @@ static void render_tile_processor(Render *re, int firsttile) re->i.partsdone++; re->stats_draw(&re->i); } - free_render_result(pa->result); + RE_FreeRenderResult(pa->result); pa->result= NULL; } if(re->test_break()) @@ -1143,7 +1335,7 @@ static void threaded_tile_processor(Render *re) int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; /* first step; the entire render result, or prepare exr buffer saving */ - free_render_result(re->result); + RE_FreeRenderResult(re->result); rr= re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE); if(rr==NULL) @@ -1155,7 +1347,7 @@ static void threaded_tile_processor(Render *re) initparts(re); if(rr->exrhandle) { - char str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; render_unique_exr_name(re, str); @@ -1213,7 +1405,7 @@ static void threaded_tile_processor(Render *re) re->display_draw(pa->result, NULL); print_part_stats(re, pa); - free_render_result(pa->result); + RE_FreeRenderResult(pa->result); pa->result= NULL; re->i.partsdone++; hasdrawn= 1; @@ -1361,7 +1553,7 @@ static void do_render_blur_3d(Render *re) } /* swap results */ - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= rres; set_mblur_offs(0.0f); @@ -1467,9 +1659,9 @@ static void do_render_fields_3d(Render *re) else merge_renderresult_fields(re->result, rr1, rr2); - free_render_result(rr2); + RE_FreeRenderResult(rr2); } - free_render_result(rr1); + RE_FreeRenderResult(rr1); re->i.curfield= 0; /* stats */ @@ -1481,7 +1673,7 @@ static void do_render_fields_3d(Render *re) static void load_backbuffer(Render *re) { if(re->r.alphamode == R_ADDSKY) { - Image *bima; + ImBuf *ibuf; char name[256]; strcpy(name, re->r.backbuf); @@ -1489,32 +1681,21 @@ static void load_backbuffer(Render *re) if(re->backbuf) { re->backbuf->id.us--; - bima= re->backbuf; + if(re->backbuf->id.us<1) + BKE_image_signal(re->backbuf, NULL, IMA_SIGNAL_RELOAD); } - else bima= NULL; - - re->backbuf= add_image(name); - if(bima && bima->id.us<1) { - free_image_buffers(bima); - } - - if(re->backbuf && re->backbuf->ibuf==NULL) { - re->backbuf->ibuf= IMB_loadiffname(re->backbuf->name, IB_rect); - if(re->backbuf->ibuf==NULL) - re->backbuf->ok= 0; - else { - re->backbuf->ok= 1; - - if (re->r.mode & R_FIELDS) - image_de_interlace(re->backbuf, re->r.mode & R_ODDFIELD); - } - } - if(re->backbuf==NULL || re->backbuf->ok==0) { + re->backbuf= BKE_add_image_file(name); + ibuf= BKE_image_get_ibuf(re->backbuf, NULL); + if(ibuf==NULL) { // error() doesnt work with render window open //error("No backbuf there!"); printf("Error: No backbuf %s\n", name); } + else { + if (re->r.mode & R_FIELDS) + image_de_interlace(re->backbuf, re->r.mode & R_ODDFIELD); + } } } @@ -1561,7 +1742,7 @@ static void do_render_fields_blur_3d(Render *re) rres= new_render_result(re, &re->disprect, 0, RR_USEMEM); merge_render_result(rres, re->result); - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= rres; /* weak... the display callback wants an active renderlayer pointer... */ @@ -1716,7 +1897,7 @@ static void do_render_composite_fields_blur_3d(Render *re) /* yafray: main yafray render/export call */ static void yafrayRender(Render *re) { - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); // need this too, for aspect/ortho/etc info @@ -1756,7 +1937,7 @@ static void yafrayRender(Render *re) rres= new_render_result(re, &re->disprect, 0, RR_USEMEM); merge_render_result(rres, re->result); - free_render_result(re->result); + RE_FreeRenderResult(re->result); re->result= rres; re->display_init(re->result); @@ -1776,12 +1957,14 @@ static void yafrayRender(Render *re) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - /* main loop: doing sequence + fields + blur + 3d render + compositing */ static void do_render_all_options(Render *re) { re->i.starttime= PIL_check_seconds_timer(); + /* ensure no images are in memory from previous animated sequences */ + BKE_image_all_free_anim_ibufs(re->r.cfra); + if(re->r.scemode & R_DOSEQ) { /* note: do_render_seq() frees rect32 when sequencer returns float images */ if(!re->test_break()) @@ -1802,6 +1985,9 @@ static void do_render_all_options(Render *re) #endif } + /* for UI only */ + renderresult_add_names(re->result); + re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; re->stats_draw(&re->i); } @@ -1835,7 +2021,7 @@ static int is_rendering_allowed(Render *re) } if(re->r.scemode & R_EXR_TILE_FILE) { - char str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; render_unique_exr_name(re, str); @@ -1964,7 +2150,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) { - char name[FILE_MAXDIR+FILE_MAXFILE]; + char name[FILE_MAX]; RenderResult rres; RE_GetResultImage(re, &rres); @@ -1983,40 +2169,49 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) MEM_freeN(rres.rect32); } printf("Append frame %d", scene->r.cfra); - } else { - ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0); - int ok; - + } + else { BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); - - /* if not exists, BKE_write_ibuf makes one */ - ibuf->rect= rres.rect32; - ibuf->rect_float= rres.rectf; - ibuf->zbuf_float= rres.rectz; - /* float factor for random dither, imbuf takes care of it */ - ibuf->dither= scene->r.dither_intensity; - - ok= BKE_write_ibuf(ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); - - if(ok==0) { - printf("Render error: cannot save %s\n", name); - G.afbreek=1; + if(re->r.imtype==R_MULTILAYER) { + if(re->result) { + RE_WriteRenderResult(re->result, name); + printf("Saved: %s", name); + } } - else printf("Saved: %s", name); - - /* optional preview images for exr */ - if(ok && scene->r.imtype==R_OPENEXR && (scene->r.subimtype & R_PREVIEW_JPG)) { - if(BLI_testextensie(name, ".exr")) - name[strlen(name)-4]= 0; - BKE_add_image_extension(name, R_JPEG90); - ibuf->depth= 24; - BKE_write_ibuf(ibuf, name, R_JPEG90, scene->r.subimtype, scene->r.quality); - printf("\nSaved: %s", name); + else { + ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0); + int ok; + + /* if not exists, BKE_write_ibuf makes one */ + ibuf->rect= rres.rect32; + ibuf->rect_float= rres.rectf; + ibuf->zbuf_float= rres.rectz; + + /* float factor for random dither, imbuf takes care of it */ + ibuf->dither= scene->r.dither_intensity; + + ok= BKE_write_ibuf(ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); + + if(ok==0) { + printf("Render error: cannot save %s\n", name); + G.afbreek=1; + } + else printf("Saved: %s", name); + + /* optional preview images for exr */ + if(ok && scene->r.imtype==R_OPENEXR && (scene->r.subimtype & R_PREVIEW_JPG)) { + if(BLI_testextensie(name, ".exr")) + name[strlen(name)-4]= 0; + BKE_add_image_extension(name, R_JPEG90); + ibuf->depth= 24; + BKE_write_ibuf(ibuf, name, R_JPEG90, scene->r.subimtype, scene->r.quality); + printf("\nSaved: %s", name); + } + + /* imbuf knows which rects are not part of ibuf */ + IMB_freeImBuf(ibuf); } - - /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); } BLI_timestr(re->i.lastframetime, name); @@ -2083,6 +2278,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) /* note; repeated win/disprect calc... solve that nicer, also in compo */ +/* only temp file! */ void RE_ReadRenderResult(Scene *scene, Scene *scenode) { Render *re; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index e6bb07ff20b..0ebd778754e 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -48,6 +48,7 @@ #include "DNA_meshdata_types.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_texture.h" @@ -1330,6 +1331,7 @@ typedef struct BakeShade { ZSpan *zspan; Image *ima; + ImBuf *ibuf; int rectx, recty, quad, type, vdone, ready; @@ -1457,12 +1459,16 @@ static int get_next_bake_face(BakeShade *bs) if(vlr->ob->flag & SELECT) { if(vlr->tface && vlr->tface->tpage) { Image *ima= vlr->tface->tpage; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; - if(ima->ibuf==NULL) + if(ibuf==NULL) continue; - if(ima->ibuf->rect==NULL && ima->ibuf->rect_float==NULL) + if(ibuf->rect==NULL && ibuf->rect_float==NULL) + continue; + + if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) continue; /* find the image for the first time? */ @@ -1470,10 +1476,10 @@ static int get_next_bake_face(BakeShade *bs) ima->id.flag &= ~LIB_DOIT; /* we either fill in float or char, this ensures things go fine */ - if(ima->ibuf->rect_float) - imb_freerectImBuf(ima->ibuf); + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* clear image */ - IMB_rectfill(ima->ibuf, vec); + IMB_rectfill(ibuf, vec); /* might be read by UI to set active image for display */ R.bakebuf= ima; @@ -1511,15 +1517,16 @@ static void shade_tface(BakeShade *bs) /* check valid zspan */ if(ima!=bs->ima) { bs->ima= ima; + bs->ibuf= BKE_image_get_ibuf(ima, NULL); /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); - zbuf_alloc_span(bs->zspan, ima->ibuf->x, ima->ibuf->y); + zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y); } - bs->rectx= ima->ibuf->x; - bs->recty= ima->ibuf->y; - bs->rect= ima->ibuf->rect; - bs->rect_float= ima->ibuf->rect_float; + bs->rectx= bs->ibuf->x; + bs->recty= bs->ibuf->y; + bs->rect= bs->ibuf->rect; + bs->rect_float= bs->ibuf->rect_float; bs->quad= 0; /* get pixel level vertex coordinates */ @@ -1607,10 +1614,10 @@ int RE_bake_shade_all_selected(Render *re, int type) /* filter images */ for(ima= G.main->image.first; ima; ima= ima->id.next) { if((ima->id.flag & LIB_DOIT)==0) { - - IMB_filter_extend(ima->ibuf); - IMB_filter_extend(ima->ibuf); /* 2nd pixel extra */ - ima->ibuf->userflags |= IB_BITMAPDIRTY; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + IMB_filter_extend(ibuf); + IMB_filter_extend(ibuf); /* 2nd pixel extra */ + ibuf->userflags |= IB_BITMAPDIRTY; } } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 04f192b3d7d..3860ca1f4c4 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -47,6 +47,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "BKE_image.h" #include "BKE_plugin_types.h" #include "BKE_utildefines.h" @@ -73,112 +74,26 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* prototypes */ -static int calcimanr(int cfra, Tex *tex); -/* ------------------------------------------------------------------------- */ -int calcimanr(int cfra, Tex *tex) +/* note; this is called WITH RENDER IS NULL in src/drawview.c for animated + background image, option should move to kernel */ +void init_render_texture(Render *re, Tex *tex) { - int imanr, len, a, fra, dur; - - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - - if(tex->frames==0) return 1; - - cfra= cfra-tex->sfra+1; - - /* cyclic */ - if(tex->len==0) len= (tex->fie_ima*tex->frames)/2; - else len= tex->len; - - if(tex->imaflag & TEX_ANIMCYCLIC) { - cfra= ( (cfra) % len ); - if(cfra < 0) cfra+= len; - if(cfra==0) cfra= len; - } - - if(cfra<1) cfra= 1; - else if(cfra>len) cfra= len; + int cfra= G.scene->r.cfra; - /* convert current frame to current field */ - cfra= 2*(cfra); - if(R.flag & R_SEC_FIELD) cfra++; + if(re) cfra= re->r.cfra; - /* transform to images space */ - imanr= (cfra+tex->fie_ima-2)/tex->fie_ima; - if(imanr>tex->frames) imanr= tex->frames; - imanr+= tex->offset; - - if(tex->imaflag & TEX_ANIMCYCLIC) { - imanr= ( (imanr) % len ); - while(imanr < 0) imanr+= len; - if(imanr==0) imanr= len; - } - - /* are there images that last longer? */ - for(a=0; a<4; a++) { - if(tex->fradur[a][0]) { - - fra= tex->fradur[a][0]; - dur= tex->fradur[a][1]-1; - - while(dur>0 && imanr>fra) { - imanr--; - dur--; - } - } - } - - return imanr; -} - -/* note; this function is called in src/drawview.c for animated background image, option should move to kernel */ -void init_render_texture(Render *re, Tex *tex) -{ - Image *ima; - int imanr; - unsigned short numlen; - char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXDIR+FILE_MAXFILE]; - /* imap test */ - if(tex->frames && tex->ima && tex->ima->name) { /* frames */ - strcpy(name, tex->ima->name); - - imanr= calcimanr(G.scene->r.cfra, tex); - - if(tex->imaflag & TEX_ANIM5) { - if(tex->ima->lastframe != imanr) { - if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf); - tex->ima->ibuf= 0; - tex->ima->lastframe= imanr; - } - } - else { - /* for patch field-ima rendering */ - tex->ima->lastframe= imanr; - - BLI_stringdec(name, head, tail, &numlen); - BLI_stringenc(name, head, tail, numlen, imanr); - - ima= add_image(name); - - if(ima) { - ima->flag |= IMA_FROMANIM; - - if(tex->ima) tex->ima->id.us--; - tex->ima= ima; - - ima->ok= 1; - } - } + if(tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + BKE_image_user_calc_imanr(&tex->iuser, cfra, re?re->flag & R_SEC_FIELD:0); } if(tex->type==TEX_PLUGIN) { if(tex->plugin && tex->plugin->doit) { - if(tex->plugin->cfra) { - *(tex->plugin->cfra)= frame_to_float(G.scene->r.cfra); - } + if(tex->plugin->cfra) { + *(tex->plugin->cfra)= frame_to_float(cfra); + } } } else if(tex->type==TEX_ENVMAP) { @@ -191,7 +106,7 @@ void init_render_texture(Render *re, Tex *tex) tex->extend= TEX_EXTEND; /* only free envmap when rendermode was set to render envmaps, for previewrender */ - if(G.rendering) { + if(G.rendering && re) { if (re->r.mode & R_ENVMAP) if(tex->env->stype==ENV_ANIM) BKE_free_envmapdata(tex->env); @@ -211,8 +126,6 @@ void init_render_textures(Render *re) if(tex->id.us) init_render_texture(re, tex); tex= tex->id.next; } - - free_unused_animimages(); } /* ------------------------------------------------------------------------- */ @@ -1189,8 +1102,8 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, retval= texnoise(tex, texres); break; case TEX_IMAGE: - if(osatex) retval= imagewraposa(tex, tex->ima, texvec, dxt, dyt, texres); - else retval= imagewrap(tex, tex->ima, texvec, texres); + if(osatex) retval= imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres); + else retval= imagewrap(tex, tex->ima, NULL, texvec, texres); tag_image_time(tex->ima); /* tag image as having being used */ break; case TEX_PLUGIN: @@ -2486,8 +2399,8 @@ void render_realtime_texture(ShadeInput *shi) texr.nor= NULL; - if(shi->osatex) imagewraposa(tex, ima, texvec, dx, dy, &texr); - else imagewrap(tex, ima, texvec, &texr); + if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); + else imagewrap(tex, ima, NULL, texvec, &texr); shi->vcol[0]*= texr.tr; shi->vcol[1]*= texr.tg; diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index cdc99f13b82..d8b69e41255 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -100,29 +100,8 @@ char texstr[20][12]= {"None" , "Clouds" , "Wood", "Marble", "Magic" , "Blend", void test_idbutton_cb(void *namev, void *arg2) { char *name= namev; - test_idbutton(name+2); - /* temporal! image rename for procedural Image has issues */ - if(arg2 && GS(name)==ID_IM) { - /* when name changed */ - if(strcmp(name+2, (char *)arg2)) { - ID *id= NULL; - if(strcmp((char *)arg2, "Render Result")==0) - id= find_id(name, name+2); - else if(strcmp((char *)arg2, "Compositor")==0) - id= find_id(name, name+2); - if(id) { - Image *ima= (Image *)id; - if(ima->ibuf) { - /* ibuf rect or rect_float is possibly not allocated but borrowed */ - ImBuf *ibuf= IMB_dupImBuf(ima->ibuf); - IMB_freeImBuf(ima->ibuf); - ima->ibuf= ibuf; - printf("changed ima %s\n", name); - } - } - } - } + test_idbutton(name+2); } diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 2d76f4f5ca9..059afee3cf3 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -124,7 +124,7 @@ void playback_anim(void); /* ************************ SOUND *************************** */ static void load_new_sample(char *str) /* called from fileselect */ { - char name[FILE_MAXDIR+FILE_MAXFILE]; + char name[FILE_MAX]; bSound *sound; bSample *sample, *newsample; @@ -164,7 +164,7 @@ static void load_new_sample(char *str) /* called from fileselect */ void do_soundbuts(unsigned short event) { - char name[FILE_MAXDIR+FILE_MAXFILE]; + char name[FILE_MAX]; bSound *sound; bSample *sample; bSound* tempsound; @@ -481,11 +481,10 @@ static void backbuf_pic(char *name) strcpy(G.scene->r.backbuf, name); allqueue(REDRAWBUTSSCENE, 0); - ima= add_image(name); - if(ima) { - free_image_buffers(ima); /* force read again */ - ima->ok= 1; - } + ima= BKE_add_image_file(name); + if(ima) + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BIF_undo_push("Change background picture"); } @@ -498,7 +497,7 @@ static void ftype_pic(char *name) static void run_playanim(char *file) { extern char bprogname[]; /* usiblender.c */ - char str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; int pos[2], size[2]; /* use current settings for defining position of window. it actually should test image size */ @@ -511,7 +510,7 @@ static void run_playanim(char *file) void playback_anim(void) { - char file[FILE_MAXDIR+FILE_MAXFILE]; + char file[FILE_MAX]; if(BKE_imtype_is_movie(G.scene->r.imtype)) { switch (G.scene->r.imtype) { @@ -1115,6 +1114,8 @@ static char *imagetype_pup(void) strcpy(formatstring, "|%s %%x%d"); sprintf(appendstring, formatstring, "OpenEXR", R_OPENEXR); strcat(string, appendstring); + sprintf(appendstring, formatstring, "MultiLayer", R_MULTILAYER); + strcat(string, appendstring); #endif if (G.have_libtiff) { @@ -1815,7 +1816,8 @@ static void render_panel_layers(void) uiDefButS(block, MENU, B_ADD_RENDERLAYER, strp, 30,145,23,20, &(G.scene->r.actlay), 0, 0, 0, 0, "Choose Active Render Layer"); MEM_freeN(strp); - bt= uiDefBut(block, TEX, REDRAWNODE, "", 53,145,172,20, srl->name, 0.0, 31.0, 0, 0, ""); + /* name max 20, exr format limit... */ + bt= uiDefBut(block, TEX, REDRAWNODE, "", 53,145,172,20, srl->name, 0.0, 20.0, 0, 0, ""); uiButSetFunc(bt, rename_scene_layer_func, srl, NULL); uiDefButBitS(block, TOG, R_SINGLE_LAYER, B_NOP, "Single", 230,145,60,20, &G.scene->r.scemode, 0, 0, 0, 0, "Only render this layer"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 2dcf7b001da..8557cea5468 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -81,6 +81,7 @@ #include "BDR_drawmesh.h" +#include "BIF_drawimage.h" #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_keyval.h" @@ -102,15 +103,12 @@ #include "blendef.h" #include "radio.h" +#include "RE_pipeline.h" + /* -----includes for this file specific----- */ #include "butspace.h" // own module -/* ---------function prototypes ------------- */ -void load_tex_image(char *); -void load_plugin_tex(char *); - -void save_env(char *); static MTex emptytex; static int packdummy = 0; @@ -178,40 +176,37 @@ void shade_buttons_change_3d(void) /* *************************** TEXTURE ******************************** */ -Tex *cur_imatex=0; -int prv_win= 0; - -void load_tex_image(char *str) /* called from fileselect */ +static void load_image_cb(char *str, void *ima_pp_v, void *iuser_v) /* called from fileselect or button */ { - Image *ima=0; - Tex *tex; + Image **ima_pp= (Image **)ima_pp_v; + Image *ima= NULL; - tex= cur_imatex; - if(tex->type==TEX_IMAGE || tex->type==TEX_ENVMAP) { + ima= BKE_add_image_file(str); + if(ima) { + if(*ima_pp) { + (*ima_pp)->id.us--; + } + *ima_pp= ima; - ima= add_image(str); - if(ima) { - if(tex->ima) { - tex->ima->id.us--; + BKE_image_signal(ima, iuser_v, IMA_SIGNAL_RELOAD); + + /* button event gets lost when it goes via filewindow */ + if(G.buts && G.buts->lockpoin) { + Tex *tex= G.buts->lockpoin; + if(GS(tex->id.name)==ID_TE) { + BIF_preview_changed(ID_TE); + allqueue(REDRAWBUTSSHADING, 0); } - tex->ima= ima; - - free_image_buffers(ima); /* force reading again */ - ima->ok= 1; } - - BIF_undo_push("Load image"); - allqueue(REDRAWBUTSSHADING, 0); - - BIF_preview_changed(ID_TE); } + + BIF_undo_push("Load image"); } -void load_plugin_tex(char *str) /* called from fileselect */ +static void load_plugin_tex(char *str, void *tex_v, void *unused) /* called from fileselect */ { - Tex *tex; + Tex *tex= tex_v; - tex= cur_imatex; if(tex->type!=TEX_PLUGIN) return; if(tex->plugin) free_plugin_tex(tex->plugin); @@ -223,10 +218,10 @@ void load_plugin_tex(char *str) /* called from fileselect */ BIF_preview_changed(ID_TE); } -void save_env(char *name) +static void save_env(char *name) { Tex *tex; - char str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; strcpy(str, name); BLI_convertstringcode(str, G.sce, G.scene->r.cfra); @@ -255,11 +250,8 @@ static int vergcband(const void *a1, const void *a2) void do_texbuts(unsigned short event) { Tex *tex; - ImBuf *ibuf; ScrArea *sa; - ID *id; - int nr; - char *name, str[FILE_MAXDIR+FILE_MAXFILE]; + char str[FILE_MAX]; tex= G.buts->lockpoin; @@ -279,7 +271,7 @@ void do_texbuts(unsigned short event) allqueue(REDRAWBUTSSHADING, 0); break; case B_TEXTYPE: - if(tex==0) return; + if(tex==NULL) return; tex->stype= 0; allqueue(REDRAWBUTSSHADING, 0); BIF_preview_changed(ID_TE); @@ -290,175 +282,41 @@ void do_texbuts(unsigned short event) } break; case B_DEFTEXVAR: - if(tex==0) return; + if(tex==NULL) return; default_tex(tex); BIF_undo_push("Default texture vars"); allqueue(REDRAWBUTSSHADING, 0); BIF_preview_changed(ID_TE); break; - case B_LOADTEXIMA: - if(tex==0) return; - /* globals: temporal store them: we make another area a fileselect */ - cur_imatex= tex; - prv_win= curarea->win; - sa= closest_bigger_area(); - areawinset(sa->win); - if(tex->ima) name= tex->ima->name; -#ifdef _WIN32 - else { - if (strcmp (U.textudir, "/") == 0) - name= G.sce; - else - name= U.textudir; - } -#else - else name = U.textudir; -#endif - - if(G.qual==LR_CTRLKEY) - activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_tex_image); - else - activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_tex_image); - - break; - case B_NAMEIMA: - if(tex==0) return; - if(tex->ima) { - cur_imatex= tex; - prv_win= curarea->win; - - /* name in tex->ima has been changed by button! */ - strcpy(str, tex->ima->name); - if(tex->ima->ibuf) strcpy(tex->ima->name, tex->ima->ibuf->name); - - load_tex_image(str); - } - break; - case B_TEXREDR_PRV: - allqueue(REDRAWBUTSSHADING, 0); + case B_IMAGECHANGED: BIF_preview_changed(ID_TE); - shade_buttons_change_3d(); - break; - case B_TEXIMABROWSE: + allqueue(REDRAWBUTSSHADING, 0); + if(tex) { - id= (ID*) tex->ima; - - if(G.buts->menunr== -2) { - activate_databrowse(id, ID_IM, 0, B_TEXIMABROWSE, &G.buts->menunr, do_texbuts); - } else if (G.buts->menunr>0) { - Image *newima= (Image*) BLI_findlink(&G.main->image, G.buts->menunr-1); - - if (newima && newima!=(Image*) id) { - tex->ima= newima; - id_us_plus((ID*) newima); - if(id) id->us--; - - BIF_undo_push("Browse image"); - allqueue(REDRAWBUTSSHADING, 0); - BIF_preview_changed(ID_TE); - } + if(G.scene->nodetree) { + NodeTagIDChanged(G.scene->nodetree, &tex->id); + allqueue(RECALC_COMPOSITE, 0); } - } - break; - case B_IMAPTEST: - if(tex) { - if( (tex->imaflag & (TEX_FIELDS+TEX_MIPMAP))== TEX_FIELDS+TEX_MIPMAP ) { + if(tex->ima && (tex->imaflag & TEX_MIPMAP) && (tex->ima->flag & IMA_FIELDS)) { error("Cannot combine fields and mipmap"); tex->imaflag -= TEX_MIPMAP; - allqueue(REDRAWBUTSSHADING, 0); - } - - if(tex->ima && tex->ima->ibuf) { - ibuf= tex->ima->ibuf; - nr= 0; - if( !(tex->imaflag & TEX_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1; - if( (tex->imaflag & TEX_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1; - if(nr) { - IMB_freeImBuf(ibuf); - tex->ima->ibuf= 0; - tex->ima->ok= 1; - BIF_preview_changed(ID_TE); - } } - } - break; - case B_RELOADIMA: - if(tex && tex->ima) { - // check if there is a newer packedfile - - if (tex->ima->packedfile) { - PackedFile *pf; - pf = newPackedFile(tex->ima->name); - if (pf) { - freePackedFile(tex->ima->packedfile); - tex->ima->packedfile = pf; - } else { - error("Image not available. Keeping packed image."); - } - } - if (tex->ima->preview) { - free_image_preview(tex->ima); - } - - IMB_freeImBuf(tex->ima->ibuf); - tex->ima->ibuf= NULL; - tex->ima->ok= 1; - if(tex->env) BKE_free_envmapdata(tex->env); - - free_realtime_image(tex->ima); - - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); - BIF_preview_changed(ID_TE); - } - allqueue(REDRAWBUTSSHADING, 0); // redraw buttons - - break; - case B_UNLINKIMA: - if(tex && tex->ima) { - tex->ima->id.us--; - tex->ima= NULL; - allqueue(REDRAWBUTSSHADING, 0); // redraw buttons - BIF_preview_changed(ID_TE); } + break; - case B_TEXSETFRAMES: - if(tex->ima->anim) tex->frames = IMB_anim_get_duration(tex->ima->anim); + + case B_TEXREDR_PRV: allqueue(REDRAWBUTSSHADING, 0); + BIF_preview_changed(ID_TE); + shade_buttons_change_3d(); break; - case B_PACKIMA: - if(tex && tex->ima) { - if (tex->ima->packedfile) { - if (G.fileflags & G_AUTOPACK) { - if (okee("Disable AutoPack ?")) { - G.fileflags &= ~G_AUTOPACK; - } - } - - if ((G.fileflags & G_AUTOPACK) == 0) { - unpackImage(tex->ima, PF_ASK); - } - } else { - if (tex->ima->ibuf && (tex->ima->ibuf->userflags & IB_BITMAPDIRTY)) { - error("Can't pack painted image. Save image from Image window first."); - } else { - tex->ima->packedfile = newPackedFile(tex->ima->name); - } - } - allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWHEADERS, 0); - } - break; - case B_LOADPLUGIN: - if(tex==0) return; - /* globals: store temporal: we make another area a fileselect */ - cur_imatex= tex; - prv_win= curarea->win; + case B_LOADPLUGIN: + if(tex==NULL) return; sa= closest_bigger_area(); areawinset(sa->win); @@ -466,12 +324,12 @@ void do_texbuts(unsigned short event) else { strcpy(str, U.plugtexdir); } - activate_fileselect(FILE_SPECIAL, "SELECT PLUGIN", str, load_plugin_tex); + activate_fileselect_args(FILE_SPECIAL, "SELECT PLUGIN", str, load_plugin_tex, tex, NULL); break; case B_NAMEPLUGIN: - if(tex==0 || tex->plugin==0) return; + if(tex==NULL || tex->plugin==NULL) return; strcpy(str, tex->plugin->name); free_plugin_tex(tex->plugin); tex->stype= 0; @@ -481,8 +339,8 @@ void do_texbuts(unsigned short event) break; case B_COLORBAND: - if(tex==0) return; - if(tex->coba==0) tex->coba= add_colorband(0); + if(tex==NULL) return; + if(tex->coba==NULL) tex->coba= add_colorband(0); allqueue(REDRAWBUTSSHADING, 0); BIF_preview_changed(ID_TE); // also ramps, so we do this break; @@ -854,11 +712,559 @@ static void texture_panel_voronoi(Tex *tex) } +static char *layer_menu(RenderResult *rr, short *curlay) +{ + RenderLayer *rl; + int len= 64 + 32*BLI_countlist(&rr->layers); + short a, nr= 0; + char *str= MEM_callocN(len, "menu layers"); + + strcpy(str, "Layer %t"); + a= strlen(str); + + /* compo result */ + if(rr->rectf) { + a+= sprintf(str+a, "|Composite %%x0"); + nr= 1; + } + for(rl= rr->layers.first; rl; rl= rl->next, nr++) { + a+= sprintf(str+a, "|%s %%x%d", rl->name, nr); + } + + if(*curlay >= nr) + *curlay= 0; + + return str; +} + +/* rl==NULL means composite result */ +static char *pass_menu(RenderLayer *rl, short *curpass) +{ + RenderPass *rpass; + int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1); + short a, nr= 0; + char *str= MEM_callocN(len, "menu layers"); + + strcpy(str, "Pass %t"); + a= strlen(str); + + /* rendered results don't have a Combined pass */ + if(rl==NULL || rl->rectf) { + a+= sprintf(str+a, "|Combined %%x0"); + nr= 1; + } + + if(rl) + for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++) + a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr); + + if(*curpass >= nr) + *curpass= 0; + + return str; +} + +static void set_frames_cb(void *ima_v, void *iuser_v) +{ + Image *ima= ima_v; + ImageUser *iuser= iuser_v; + + if(ima->anim) { + iuser->frames = IMB_anim_get_duration(ima->anim); + BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0); + } +} + +static void image_src_change_cb(void *ima_v, void *iuser_v) +{ + BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_SRC_CHANGE); +} + +/* buttons have 2 arg callbacks, filewindow has 3 args... so thats why the wrapper below */ +static void image_browse_cb1(char *unused, void *ima_pp_v, void *iuser_v) +{ + Image **ima_pp= (Image **)ima_pp_v; + ImageUser *iuser= iuser_v; + + if(ima_pp) { + Image *ima= *ima_pp; + + if(iuser->menunr== -2) { + activate_databrowse_args(&ima->id, ID_IM, 0, &iuser->menunr, image_browse_cb1, ima_pp, iuser); + } + else if (iuser->menunr>0) { + Image *newima= (Image*) BLI_findlink(&G.main->image, iuser->menunr-1); + + if (newima && newima!=ima) { + *ima_pp= newima; + id_us_plus(&newima->id); + if(ima) ima->id.us--; + + BKE_image_signal(newima, iuser, IMA_SIGNAL_USER_NEW_IMAGE); + + BIF_undo_push("Browse image"); + } + } + } +} + +static void image_browse_cb(void *ima_pp_v, void *iuser_v) +{ + image_browse_cb1(NULL, ima_pp_v, iuser_v); +} + +static void image_reload_cb(void *ima_v, void *iuser_v) +{ + if(ima_v) { + BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_RELOAD); + } +} + +static void image_field_test(void *ima_v, void *iuser_v) +{ + Image *ima= ima_v; + + if(ima) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v); + if(ibuf) { + short nr= 0; + if( !(ima->flag & IMA_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1; + if( (ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1; + if(nr) { + BKE_image_signal(ima, iuser_v, IMA_SIGNAL_FREE); + } + } + } +} + +static void image_unlink_cb(void *ima_pp_v, void *unused) +{ + Image **ima_pp= (Image **)ima_pp_v; + + if(ima_pp && *ima_pp) { + Image *ima= *ima_pp; + ima->id.us--; + *ima_pp= NULL; + } +} + +static void image_load_fs_cb(void *ima_pp_v, void *iuser_v) +{ + Image **ima_pp= (Image **)ima_pp_v; + ScrArea *sa; + char *name; + + if(ima_pp==NULL) return; + + sa= closest_bigger_area(); + areawinset(sa->win); + if(*ima_pp) name= (*ima_pp)->name; +#ifdef _WIN32 + else { + if (strcmp (U.textudir, "/") == 0) + name= G.sce; + else + name= U.textudir; + } +#else + else name = U.textudir; +#endif + activate_fileselect_args(FILE_SPECIAL, "SELECT IMAGE", name, load_image_cb, ima_pp_v, iuser_v); +} + +/* 5 layer button callbacks... */ +static void image_multi_cb(void *rr_v, void *iuser_v) +{ + BKE_image_multilayer_index(rr_v, iuser_v); +} +static void image_multi_inclay_cb(void *rr_v, void *iuser_v) +{ + RenderResult *rr= rr_v; + ImageUser *iuser= iuser_v; + int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0); /* fake compo result layer */ + if(iuser->layerlayer++; + BKE_image_multilayer_index(rr, iuser); +} +static void image_multi_declay_cb(void *rr_v, void *iuser_v) +{ + ImageUser *iuser= iuser_v; + if(iuser->layer>0) + iuser->layer--; + BKE_image_multilayer_index(rr_v, iuser); +} +static void image_multi_incpass_cb(void *rr_v, void *iuser_v) +{ + RenderResult *rr= rr_v; + ImageUser *iuser= iuser_v; + RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer); + if(rl) { + int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0); /* builtin render result has no combined pass in list */ + if(iuser->passpass++; + BKE_image_multilayer_index(rr, iuser); + } + } +} +static void image_multi_decpass_cb(void *rr_v, void *iuser_v) +{ + ImageUser *iuser= iuser_v; + if(iuser->pass>0) { + iuser->pass--; + BKE_image_multilayer_index(rr_v, iuser); + } +} + +static void image_pack_cb(void *ima_v, void *iuser_v) +{ + if(ima_v) { + Image *ima= ima_v; + if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) { + if (ima->packedfile) { + if (G.fileflags & G_AUTOPACK) { + if (okee("Disable AutoPack ?")) { + G.fileflags &= ~G_AUTOPACK; + } + } + + if ((G.fileflags & G_AUTOPACK) == 0) { + unpackImage(ima, PF_ASK); + BIF_undo_push("Unpack image"); + } + } + else { + ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v); + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + error("Can't pack painted image. Save image or use Repack as PNG."); + } else { + ima->packedfile = newPackedFile(ima->name); + BIF_undo_push("Pack image"); + } + } + } + } +} + +static void image_load_cb(void *ima_pp_v, void *iuser_v) +{ + if(ima_pp_v) { + Image *ima= *((Image **)ima_pp_v); + ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v); + char str[FILE_MAX]; + + /* name in ima has been changed by button! */ + BLI_strncpy(str, ima->name, FILE_MAX); + if(ibuf) BLI_strncpy(ima->name, ibuf->name, FILE_MAX); + + load_image_cb(str, ima_pp_v, iuser_v); + } +} + +static void image_freecache_cb(void *ima_v, void *unused) +{ + BKE_image_free_anim_ibufs(ima_v, G.scene->r.cfra); + allqueue(REDRAWIMAGE, 0); +} + +static void image_generated_change_cb(void *ima_v, void *iuser_v) +{ + BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_FREE); +} + +static void image_user_change(void *iuser_v, void *unused) +{ + BKE_image_user_calc_imanr(iuser_v, G.scene->r.cfra, 0); +} + +void uiblock_layer_pass_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int event, int x, int y, int w) +{ + uiBut *but; + RenderLayer *rl= NULL; + int wmenu1, wmenu2; + char *strp; + + /* layer menu is 1/3 larger than pass */ + wmenu1= (3*w)/5; + wmenu2= (2*w)/5; + + /* menu buts */ + strp= layer_menu(rr, &iuser->layer); + but= uiDefButS(block, MENU, event, strp, x, y, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer"); + uiButSetFunc(but, image_multi_cb, rr, iuser); + MEM_freeN(strp); + + rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */ + strp= pass_menu(rl, &iuser->pass); + but= uiDefButS(block, MENU, event, strp, x+wmenu1, y, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass"); + uiButSetFunc(but, image_multi_cb, rr, iuser); + MEM_freeN(strp); +} + +static void uiblock_layer_pass_arrow_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int imagechanged) +{ + uiBut *but; + + if(rr==NULL || iuser==NULL) + return; + if(rr->layers.first==NULL) { + uiDefBut(block, LABEL, 0, "No Layers in Render Result,", 10, 107, 300, 20, NULL, 1, 0, 0, 0, ""); + return; + } + + uiBlockBeginAlign(block); + + /* decrease, increase arrows */ + but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 10,107,17,20, NULL, 0, 0, 0, 0, "Previous Layer"); + uiButSetFunc(but, image_multi_declay_cb, rr, iuser); + but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 27,107,18,20, NULL, 0, 0, 0, 0, "Next Layer"); + uiButSetFunc(but, image_multi_inclay_cb, rr, iuser); + + uiblock_layer_pass_buttons(block, rr, iuser, imagechanged, 45, 107, 230); + + /* decrease, increase arrows */ + but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 275,107,17,20, NULL, 0, 0, 0, 0, "Previous Pass"); + uiButSetFunc(but, image_multi_decpass_cb, rr, iuser); + but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 292,107,18,20, NULL, 0, 0, 0, 0, "Next Pass"); + uiButSetFunc(but, image_multi_incpass_cb, rr, iuser); + + uiBlockEndAlign(block); + +} + +/* The general Image panel with the loadsa callbacks! */ +void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, + short redraw, short imagechanged) +{ + Image *ima= *ima_pp; + uiBut *but; + char str[128], *strp; + + /* different stuff when we show viewer */ + if(ima && ima->source==IMA_SRC_VIEWER) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser); + + image_info(ima, ibuf, str); + uiDefBut(block, LABEL, 0, ima->id.name+2, 10, 180, 300, 20, NULL, 1, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, str, 10, 160, 300, 20, NULL, 1, 0, 0, 0, ""); + + if(ima->type==IMA_TYPE_COMPOSITE) { + iuser= ntree_get_active_iuser(G.scene->nodetree); + + uiBlockBeginAlign(block); + uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, ""); + uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110,120,100,20, 0, 0, 0, 0, 0, ""); + but= uiDefBut(block, BUT, B_NOP, "Free Cache", 210,120,100,20, 0, 0, 0, 0, 0, ""); + uiButSetFunc(but, image_freecache_cb, ima, NULL); + + if(iuser->frames) + sprintf(str, "(%d) Frames:", iuser->framenr); + else strcpy(str, "Frames:"); + uiBlockBeginAlign(block); + uiDefButI(block, NUM, imagechanged, str, 10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); + } + else if(ima->type==IMA_TYPE_R_RESULT) { + /* browse layer/passes */ + uiblock_layer_pass_arrow_buttons(block, RE_GetResult(RE_GetRender(G.scene->id.name)), iuser, imagechanged); + } + return; + } + + /* the main ima source types */ + if(ima) { + uiSetButLock(ima->id.lib!=NULL, "Can't edit library data"); + uiBlockBeginAlign(block); + uiBlockSetFunc(block, image_src_change_cb, ima, iuser); + uiDefButS(block, ROW, imagechanged, "Still", 10, 180, 60, 20, &ima->source, 0.0, IMA_SRC_FILE, 0, 0, "Single Image file"); + uiDefButS(block, ROW, imagechanged, "Movie", 70, 180, 60, 20, &ima->source, 0.0, IMA_SRC_MOVIE, 0, 0, "Movie file"); + uiDefButS(block, ROW, imagechanged, "Sequence", 130, 180, 90, 20, &ima->source, 0.0, IMA_SRC_SEQUENCE, 0, 0, "Multiple Image files, as a sequence"); + uiDefButS(block, ROW, imagechanged, "Generated", 220, 180, 90, 20, &ima->source, 0.0, IMA_SRC_GENERATED, 0, 0, "Generated Image"); + uiBlockSetFunc(block, NULL, NULL, NULL); + } + else + uiDefBut(block, LABEL, 0, " ", 10, 180, 300, 20, 0, 0, 0, 0, 0, ""); /* for align in panel */ + + /* Browse */ + IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), NULL, &iuser->menunr); + + uiBlockBeginAlign(block); + but= uiDefButS(block, MENU, imagechanged, strp, 10,155,23,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie"); + uiButSetFunc(but, image_browse_cb, ima_pp, iuser); + + MEM_freeN(strp); + + /* name + options, or only load */ + if(ima) { + int drawpack= (ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE && ima->ok); + + but= uiDefBut(block, TEX, B_IDNAME, "IM:", 33, 155, 177, 20, ima->id.name+2, 0.0, 19.0, 0, 0, "Current Image Datablock name."); + uiButSetFunc(but, test_idbutton_cb, ima->id.name, NULL); + but= uiDefBut(block, BUT, imagechanged, "Reload", 210, 155, 60, 20, NULL, 0, 0, 0, 0, "Reloads Image or Movie"); + uiButSetFunc(but, image_reload_cb, ima, iuser); + + but= uiDefIconBut(block, BUT, imagechanged, ICON_X, 270,155,20,20, 0, 0, 0, 0, 0, "Unlink Image block"); + uiButSetFunc(but, image_unlink_cb, ima_pp, NULL); + sprintf(str, "%d", ima->id.us); + uiDefBut(block, BUT, B_NOP, str, 290,155,20,20, 0, 0, 0, 0, 0, "Only displays number of users of Image block"); + + but= uiDefIconBut(block, BUT, imagechanged, ICON_FILESEL, 10, 135, 23, 20, 0, 0, 0, 0, 0, "Open Fileselect to load new Image"); + uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser); + but= uiDefBut(block, TEX, imagechanged, "", 33,135,257+(drawpack?0:20),20, ima->name, 0.0, 239.0, 0, 0, "Image/Movie file name, change to load new"); + uiButSetFunc(but, image_load_cb, ima_pp, iuser); + + if(drawpack) { + if (ima->packedfile) packdummy = 1; + else packdummy = 0; + but= uiDefIconButBitI(block, TOG, 1, redraw, ICON_PACKAGE, 290,135,20,20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this Image"); + uiButSetFunc(but, image_pack_cb, ima, iuser); + } + + } + else { + but= uiDefBut(block, BUT, imagechanged, "Load", 33, 155, 100,20, NULL, 0, 0, 0, 0, "Load new Image of Movie"); + uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser); + } + uiBlockEndAlign(block); + + if(ima) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser); + + /* check for re-render, only buttons */ + if(imagechanged==B_IMAGECHANGED) { + if(iuser->flag & IMA_ANIM_REFRESHED) { + iuser->flag &= ~IMA_ANIM_REFRESHED; + BIF_preview_changed(ID_TE); + } + } + + /* multilayer? */ + if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { + uiblock_layer_pass_arrow_buttons(block, ima->rr, iuser, imagechanged); + } + else { + image_info(ima, ibuf, str); + uiDefBut(block, LABEL, 0, str, 10, 107, 300, 20, NULL, 1, 0, 0, 0, ""); + } + + /* left side default per-image options, right half the additional options */ + + /* fields */ + uiBlockBeginAlign(block); + but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields", 10, 70, 100, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); + uiButSetFunc(but, image_field_test, ima, iuser); + uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd", 10, 50, 100, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); + uiBlockEndAlign(block); + + uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti", 10, 10, 100, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); + + if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + sprintf(str, "(%d) Frames:", iuser->framenr); + + uiBlockBeginAlign(block); + uiBlockSetFunc(block, image_user_change, iuser, NULL); + uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh", 120, 70, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes"); + + if(ima->anim) { + uiDefButI(block, NUM, imagechanged, str, 120, 50,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + but= uiDefBut(block, BUT, redraw, "<", 290, 50, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button"); + uiButSetFunc(but, set_frames_cb, ima, iuser); + } + else + uiDefButI(block, NUM, imagechanged, str, 120, 50,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + + uiDefButI(block, NUM, imagechanged, "Offs:", 120,30,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); + uiDefButS(block, NUM, imagechanged, "Fie/Ima:", 220,30,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)"); + + uiDefButI(block, NUM, imagechanged, "StartFr:", 120,10,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); + uiDefButS(block, TOG, imagechanged, "Cyclic", 220,10,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie"); + + uiBlockSetFunc(block, NULL, iuser, NULL); + } + else if(ima->source==IMA_SRC_GENERATED) { + + uiBlockBeginAlign(block); + uiBlockSetFunc(block, image_generated_change_cb, ima, iuser); + uiDefButS(block, NUM, imagechanged, "SizeX:", 120,70,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x"); + uiDefButS(block, NUM, imagechanged, "SizeY:", 220,70,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y"); + uiDefButS(block, TOG, imagechanged, "UV Test grid",120,50,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, ""); + uiBlockSetFunc(block, NULL, NULL, NULL); + } + } + +} + +static void texture_panel_image(Image **ima, ImageUser *iuser) +{ + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_image", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Image", "Texture", 960, 0, 318, 204)==0) return; + + uiblock_image_panel(block, ima, iuser, B_REDR, B_IMAGECHANGED); +} + +static void texture_panel_image_map(Tex *tex) +{ + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_image_map", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Map Image", "Texture", 640, 0, 318, 204)==0) return; + uiSetButLock(tex->id.lib!=0, "Can't edit library data"); + + /* types */ + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, TEX_MIPMAP, B_IMAGECHANGED, "MipMap", 10, 180, 75, 20, &tex->imaflag, 0, 0, 0, 0, "Generates and uses mipmaps"); + uiDefButBitS(block, TOG, TEX_GAUSS_MIP, 0, "Gauss", 85, 180, 75, 20, &tex->imaflag, 0, 0, 0, 0, "Enable Gauss filter to sample down mipmaps"); + uiDefButBitS(block, TOG, TEX_INTERPOL, 0, "Interpol", 160, 180, 75, 20, &tex->imaflag, 0, 0, 0, 0, "Interpolates pixels using Area filter"); + uiDefButBitS(block, TOG, TEX_IMAROT, B_TEXPRV, "Rot90", 235, 180, 75, 20, &tex->imaflag, 0, 0, 0, 0, "Actually flips X and Y for rendering, rotates and mirrors"); + + uiDefButBitS(block, TOG, TEX_USEALPHA, B_TEXPRV, "UseAlpha", 10, 160, 100, 20, &tex->imaflag, 0, 0, 0, 0, "Click to use Image's alpha channel"); + uiDefButBitS(block, TOG, TEX_CALCALPHA, B_TEXPRV, "CalcAlpha", 110, 160, 100, 20, &tex->imaflag, 0, 0, 0, 0, "Click to calculate an alpha channel based on Image RGB values"); + uiDefButBitS(block, TOG, TEX_NEGALPHA, B_TEXPRV, "NegAlpha", 210, 160, 100, 20, &tex->flag, 0, 0, 0, 0, "Click to invert the alpha values"); + uiBlockEndAlign(block); + + uiDefButF(block, NUM, B_TEXPRV, "Filter :", 10,120,150,20, &tex->filtersize, 0.1, 25.0, 0, 3, "Sets the filter size used by mipmap and interpol"); + + uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,120,150,20, &tex->imaflag, + 0, 0, 0, 0, "Use image RGB values for normal mapping"); + + /* crop extend clip */ + + uiBlockBeginAlign(block); + uiDefButS(block, ROW, B_TEXREDR_PRV, "Extend", 10,90,63,19, &tex->extend, 4.0, 1.0, 0, 0, "Extends the colour of the edge pixels"); + uiDefButS(block, ROW, B_TEXREDR_PRV, "Clip", 73,90,48,19, &tex->extend, 4.0, 2.0, 0, 0, "Sets alpha 0.0 outside Image edges"); + uiDefButS(block, ROW, B_TEXREDR_PRV, "ClipCube", 121,90,63,19, &tex->extend, 4.0, 4.0, 0, 0, "Sets alpha to 0.0 outside cubeshaped area around Image"); + uiDefButS(block, ROW, B_TEXREDR_PRV, "Repeat", 184,90,63,19, &tex->extend, 4.0, 3.0, 0, 0, "Causes Image to repeat horizontally and vertically"); + uiDefButS(block, ROW, B_TEXREDR_PRV, "Checker", 247,90,63,19, &tex->extend, 4.0, 5.0, 0, 0, "Causes Image to repeat in checker pattern"); + + if(tex->extend==TEX_REPEAT) { + uiBlockBeginAlign(block); + uiDefButS(block, NUM, B_TEXPRV, "Xrepeat:", 10,60,150,19, &tex->xrepeat, 1.0, 512.0, 0, 0, "Sets a repetition multiplier in the X direction"); + uiDefButS(block, NUM, B_TEXPRV, "Yrepeat:", 160,60,150,19, &tex->yrepeat, 1.0, 512.0, 0, 0, "Sets a repetition multiplier in the Y direction"); + } + else if(tex->extend==TEX_CHECKER) { + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, TEX_CHECKER_ODD, B_TEXPRV, "Odd", 10,60,100,19, &tex->flag, 0.0, 0.0, 0, 0, "Sets odd checker tiles"); + uiDefButBitS(block, TOG, TEX_CHECKER_EVEN, B_TEXPRV, "Even", 110,60,100,19, &tex->flag, 0.0, 0.0, 0, 0, "Sets even checker tiles"); + uiDefButF(block, NUM, B_TEXPRV, "Mortar:", 210,60,100,19, &tex->checkerdist, 0.0, 0.99, 0, 0, "Set checkers distance (like mortar)"); + } + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_TEXPRV, "MinX ", 10,30,150,19, &tex->cropxmin, -10.0, 10.0, 10, 0, "Sets minimum X value to crop Image"); + uiDefButF(block, NUM, B_TEXPRV, "MinY ", 10,10,150,19, &tex->cropymin, -10.0, 10.0, 10, 0, "Sets minimum Y value to crop Image"); + + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_TEXPRV, "MaxX ", 160,30,150,19, &tex->cropxmax, -10.0, 10.0, 10, 0, "Sets maximum X value to crop Image"); + uiDefButF(block, NUM, B_TEXPRV, "MaxY ", 160,10,150,19, &tex->cropymax, -10.0, 10.0, 10, 0, "Sets maximum Y value to crop Image"); + uiBlockEndAlign(block); + +} + /***************************************/ static void texture_panel_envmap(Tex *tex) { uiBlock *block; + uiBut *but; EnvMap *env; ID *id; short a, xco, yco, dx, dy; @@ -867,7 +1273,7 @@ static void texture_panel_envmap(Tex *tex) block= uiNewBlock(&curarea->uiblocks, "texture_panel_envmap", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Envmap", "Texture", 640, 0, 318, 204)==0) return; uiSetButLock(tex->id.lib!=0, "Can't edit library data"); - + if(tex->env==NULL) { tex->env= BKE_add_envmap(); tex->env->object= OBACT; @@ -884,28 +1290,35 @@ static void texture_panel_envmap(Tex *tex) if(env->stype==ENV_LOAD) { /* file input */ id= (ID *)tex->ima; - IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr)); + IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr)); if(strp[0]) { uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_TEXIMABROWSE, strp, 10,145,23,20, &(G.buts->menunr), 0, 0, 0, 0, "Selects an existing environment map or creates new"); + + but= uiDefButS(block, MENU, B_TEXPRV, strp, 10,145,23,20, &tex->iuser.menunr, 0, 0, 0, 0, "Selects an existing environment map"); + uiButSetFunc(but, image_browse_cb, &tex->ima, &tex->iuser); if(tex->ima) { - uiDefBut(block, TEX, B_NAMEIMA, "", 35,145,255,20, tex->ima->name, 0.0, 79.0, 0, 0, "Displays environment map name: click to change"); + but= uiDefBut(block, TEX, B_NAMEIMA, "", 35,145,255,20, tex->ima->name, 0.0, 79.0, 0, 0, "Displays environment map name: click to change"); + uiButSetFunc(but, image_load_cb, &tex->ima, &tex->iuser); + sprintf(str, "%d", tex->ima->id.us); uiDefBut(block, BUT, 0, str, 290,145,20,20, 0, 0, 0, 0, 0, "Displays number of users of environment map: click to make single user"); uiBlockEndAlign(block); - uiDefBut(block, BUT, B_RELOADIMA, "Reload", 230,125,80,20, 0, 0, 0, 0, 0, "Reloads saved environment map"); - + but= uiDefBut(block, BUT, B_IMAGECHANGED, "Reload", 230,125,80,20, 0, 0, 0, 0, 0, "Reloads saved environment map"); + uiButSetFunc(but, image_reload_cb, tex->ima, NULL); + if (tex->ima->packedfile) packdummy = 1; else packdummy = 0; - uiDefIconButBitI(block, TOG, 1, B_PACKIMA, ICON_PACKAGE, 205,125,24,20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this environment map"); + but= uiDefIconButBitI(block, TOG, 1, B_REDR, ICON_PACKAGE, 205,125,24,20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this environment map"); + uiButSetFunc(but, image_pack_cb, tex->ima, &tex->iuser); } else uiBlockEndAlign(block); } MEM_freeN(strp); - - uiDefBut(block, BUT, B_LOADTEXIMA, "Load Image", 10,125,150,20, 0, 0, 0, 0, 0, "Loads saved environment map - file select"); + + but= uiDefBut(block, BUT, B_IMAGECHANGED, "Load Image", 10,125,150,20, 0, 0, 0, 0, 0, "Loads saved environment map - file select"); + uiButSetFunc(but, image_load_fs_cb, &tex->ima, &tex->iuser); } else { uiBlockBeginAlign(block); @@ -919,15 +1332,15 @@ static void texture_panel_envmap(Tex *tex) uiDefButF(block, NUM, B_NOP, "Zoom: ", 210,120,100,20, &env->viewscale, 0.5f, 5.0f, 100, 2, "Zoom factor for planar environment map"); uiBlockEndAlign(block); } - + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_ENV_OB, "Ob:", 10,90,150,20, &(env->object), "Displays object to use as viewpoint for environment map: click to change"); if(env->stype!=ENV_LOAD) uiDefButS(block, NUM, B_ENV_FREE, "CubeRes", 160,90,150,20, &env->cuberes, 50, 4096.0, 0, 0, "Sets the pixel resolution of the rendered environment map"); - + uiBlockBeginAlign(block); uiDefButF(block, NUM, B_TEXPRV, "Filter :", 10,65,150,20, &tex->filtersize, 0.1, 25.0, 0, 3, "Adjusts sharpness or blurriness of the reflection"), - uiDefButS(block, NUM, B_ENV_FREE, "Depth:", 160,65,150,20, &env->depth, 0, 5.0, 0, 0, "Sets the number of times a map will be rendered recursively mirror effects"), - uiDefButF(block, NUM, REDRAWVIEW3D, "ClipSta", 10,40,150,20, &env->clipsta, 0.01, 50.0, 100, 0, "Sets start value for clipping: objects nearer than this are not visible to map"); + uiDefButS(block, NUM, B_ENV_FREE, "Depth:", 160,65,150,20, &env->depth, 0, 5.0, 0, 0, "Sets the number of times a map will be rendered recursively mirror effects"), + uiDefButF(block, NUM, REDRAWVIEW3D, "ClipSta", 10,40,150,20, &env->clipsta, 0.01, 50.0, 100, 0, "Sets start value for clipping: objects nearer than this are not visible to map"); uiDefButF(block, NUM, B_NOP, "ClipEnd", 160,40,150,20, &env->clipend, 0.1, 5000.0, 1000, 0, "Sets end value for clipping beyond which objects are not visible to map"); uiBlockEndAlign(block); @@ -942,146 +1355,15 @@ static void texture_panel_envmap(Tex *tex) uiDefButBitI(block, TOG, 1<notlay, 0, 0, 0, 0, "Toggles layer visibility to environment map"); for(a=0; a<5; a++) uiDefButBitI(block, TOG, 1<<(a+10), 0, "",(xco+a*(dx/2)), yco, (dx/2), (dy/2), &env->notlay, 0, 0, 0, 0, "Toggles layer visibility to environment map"); - + uiBlockBeginAlign(block); xco+= 5; for(a=5; a<10; a++) uiDefButBitI(block, TOG, 1<notlay, 0, 0, 0, 0, "Toggles layer visibility to environment map"); for(a=5; a<10; a++) uiDefButBitI(block, TOG, 1<<(a+10), 0, "",(xco+a*(dx/2)), yco, (dx/2), (dy/2), &env->notlay, 0, 0, 0, 0, "Toggles layer visibility to environment map"); - - } -} - - -static void texture_panel_image1(Tex *tex) -{ - uiBlock *block; - char str[32]; - - block= uiNewBlock(&curarea->uiblocks, "texture_panel1", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Anim and Movie", "Texture", 960, 0, 318, 204)==0) return; - uiSetButLock(tex->id.lib!=0, "Can't edit library data"); - - /* print amount of frames anim */ - if(tex->ima && tex->ima->anim) { - uiDefBut(block, BUT, B_TEXSETFRAMES, "<", 802, 110, 20, 18, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button"); - sprintf(str, "%d frs ", IMB_anim_get_duration(tex->ima->anim)); - uiDefBut(block, LABEL, 0, str, 834, 110, 90, 18, 0, 0, 0, 0, 0, "Number of frames in movie file"); - sprintf(str, "%d cur ", tex->ima->lastframe); - uiDefBut(block, LABEL, 0, str, 834, 90, 90, 18, 0, 0, 0, 0, 0, ""); - } - else uiDefBut(block, LABEL, 0, "<", 802, 110, 20, 18, 0, 0, 0, 0, 0, ""); - - uiDefButI(block, NUM, B_TEXPRV, "Frames :", 642,110,150,19, &tex->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of frames of a movie to use and activates animation options"); - uiDefButI(block, NUM, B_TEXPRV, "Offset :", 642,90,150,19, &tex->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the first movie frame to use in the animation"); - uiDefButS(block, NUM, B_TEXPRV, "Fie/Ima:", 642,60,98,19, &tex->fie_ima, 1.0, 200.0, 0, 0, "Sets the number of fields per rendered frame"); - uiDefButI(block, NUM, B_TEXPRV, "StartFr:", 642,30,150,19, &tex->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the starting frame of the movie to use in animation"); - uiDefButI(block, NUM, B_TEXPRV, "Len:", 642,10,150,19, &tex->len, 0.0, MAXFRAMEF, 0, 0, "Sets the number of movie frames to use in animation: 0=all"); - - uiBlockBeginAlign(block); - uiDefButI(block, NUM, B_TEXPRV, "Fra:", 802,70,73,19, &(tex->fradur[0][0]), 0.0, MAXFRAMEF, 0, 0, "Montage mode: frame start"); - uiDefButI(block, NUM, B_TEXPRV, "Fra:", 802,50,73,19, &(tex->fradur[1][0]), 0.0, MAXFRAMEF, 0, 0, "Montage mode: frame start"); - uiDefButI(block, NUM, B_TEXPRV, "Fra:", 802,30,73,19, &(tex->fradur[2][0]), 0.0, MAXFRAMEF, 0, 0, "Montage mode: frame start"); - uiDefButI(block, NUM, B_TEXPRV, "Fra:", 802,10,73,19, &(tex->fradur[3][0]), 0.0, MAXFRAMEF, 0, 0, "Montage mode: frame start"); - uiBlockBeginAlign(block); - uiDefButI(block, NUM, B_TEXPRV, "", 879,70,37,19, &(tex->fradur[0][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames"); - uiDefButI(block, NUM, B_TEXPRV, "", 879,50,37,19, &(tex->fradur[1][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames"); - uiDefButI(block, NUM, B_TEXPRV, "", 879,30,37,19, &(tex->fradur[2][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames"); - uiDefButI(block, NUM, B_TEXPRV, "", 879,10,37,19, &(tex->fradur[3][1]), 0.0, 250.0, 0, 0, "Montage mode: amount of displayed frames"); - uiBlockEndAlign(block); - uiDefButBitS(block, TOG, TEX_ANIMCYCLIC, B_TEXPRV, "Cyclic", 743,60,48,19, &tex->imaflag, 0, 0, 0, 0, "Toggles looping of animated frames"); -} - - -static void texture_panel_image(Tex *tex) -{ - uiBlock *block; - ID *id; - char *strp, str[32]; - - block= uiNewBlock(&curarea->uiblocks, "texture_panel_image", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Image", "Texture", 640, 0, 318, 204)==0) return; - uiSetButLock(tex->id.lib!=0, "Can't edit library data"); - - /* types */ - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, TEX_MIPMAP, B_IMAPTEST, "MipMap", 10, 180, 60, 18, &tex->imaflag, 0, 0, 0, 0, "Generates and uses mipmaps"); - uiDefButBitS(block, TOG, TEX_GAUSS_MIP, 0, "Gauss", 70, 180, 50, 18, &tex->imaflag, 0, 0, 0, 0, "Enable Gauss filter to sample down mipmaps"); - uiDefButBitS(block, TOG, TEX_INTERPOL, 0, "Interpol", 120, 180, 60, 18, &tex->imaflag, 0, 0, 0, 0, "Interpolates pixels using Area filter"); - uiDefButBitS(block, TOG, TEX_IMAROT, B_TEXPRV, "Rot90", 180, 180, 40, 18, &tex->imaflag, 0, 0, 0, 0, "Actually flips X and Y for rendering, rotates and mirrors"); - uiDefButBitS(block, TOG, TEX_ANTIALI, 0, "Anti", 220, 180, 40, 18, &tex->imaflag, 0, 0, 0, 0, "Toggles Image anti-aliasing"); - uiDefButBitS(block, TOG, TEX_ANIM5, B_RELOADIMA, "Movie", 260, 180, 50, 18, &tex->imaflag, 0, 0, 0, 0, "Click to enable movie frames as Images"); - - uiDefButBitS(block, TOG, TEX_USEALPHA, B_TEXPRV, "UseAlpha", 10, 160, 70, 18, &tex->imaflag, 0, 0, 0, 0, "Click to use Image's alpha channel"); - uiDefButBitS(block, TOG, TEX_CALCALPHA, B_TEXPRV, "CalcAlpha", 80, 160, 70, 18, &tex->imaflag, 0, 0, 0, 0, "Click to calculate an alpha channel based on Image RGB values"); - uiDefButBitS(block, TOG, TEX_NEGALPHA, B_TEXPRV, "NegAlpha", 150, 160, 60, 18, &tex->flag, 0, 0, 0, 0, "Click to invert the alpha values"); - uiDefButBitS(block, TOG, TEX_FIELDS, B_IMAPTEST, "Fields", 210, 160, 60, 18, &tex->imaflag, 0, 0, 0, 0, "Click to enable use of fields in Image"); - uiDefButBitS(block, TOG, TEX_STD_FIELD, 0, "Odd", 270, 160, 40, 18, &tex->imaflag, 0, 0, 0, 0, "Standard Field Toggle"); - uiBlockEndAlign(block); - - /* file input */ - id= (ID *)tex->ima; - IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(G.buts->menunr)); - if(strp[0]) { - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_TEXIMABROWSE, strp, 10,135,23,20, &(G.buts->menunr), 0, 0, 0, 0, "Selects an existing texture or creates new"); - if(tex->ima) { - uiDefBut(block, TEX, B_NAMEIMA, "", 35,135,235,20, tex->ima->name, 0.0, 79.0, 0, 0, "Displays name of the Image file: click to change"); - uiDefIconBut(block, BUT, B_UNLINKIMA, ICON_X, 270,135,20,20, 0, 0, 0, 0, 0, "Unlink Image block from Texture"); - - sprintf(str, "%d", tex->ima->id.us); - uiDefBut(block, BUT, 0, str, 290,135,20,20, 0, 0, 0, 0, 0, "Displays number of users of texture"); - uiBlockEndAlign(block); - - uiDefBut(block, BUT, B_RELOADIMA, "Reload", 230,115,80,19, 0, 0, 0, 0, 0, "Reloads Image"); - - if (tex->ima->packedfile) packdummy = 1; - else packdummy = 0; - - uiDefIconButBitI(block, TOG, 1, B_PACKIMA, ICON_PACKAGE, 205,115,24,19, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this Image"); - } - else uiBlockEndAlign(block); } - MEM_freeN(strp); - - uiDefBut(block, BUT, B_LOADTEXIMA, "Load Image", 10,115,150,19, 0, 0, 0, 0, 0, "Click to load an Image"); - - /* crop extend clip */ - - uiDefButF(block, NUM, B_TEXPRV, "Filter :", 10,92,150,19, &tex->filtersize, 0.1, 25.0, 0, 3, "Sets the filter size used by mipmap and interpol"); - - uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,92,150,19, &tex->imaflag, - 0, 0, 0, 0, "Use image RGB values for normal mapping"); - - uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_TEXREDR_PRV, "Extend", 10,70,63,19, &tex->extend, 4.0, 1.0, 0, 0, "Extends the colour of the edge pixels"); - uiDefButS(block, ROW, B_TEXREDR_PRV, "Clip", 73,70,48,19, &tex->extend, 4.0, 2.0, 0, 0, "Sets alpha 0.0 outside Image edges"); - uiDefButS(block, ROW, B_TEXREDR_PRV, "ClipCube", 121,70,63,19, &tex->extend, 4.0, 4.0, 0, 0, "Sets alpha to 0.0 outside cubeshaped area around Image"); - uiDefButS(block, ROW, B_TEXREDR_PRV, "Repeat", 184,70,63,19, &tex->extend, 4.0, 3.0, 0, 0, "Causes Image to repeat horizontally and vertically"); - uiDefButS(block, ROW, B_TEXREDR_PRV, "Checker", 247,70,63,19, &tex->extend, 4.0, 5.0, 0, 0, "Causes Image to repeat in checker pattern"); - - if(tex->extend==TEX_REPEAT) { - uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_TEXPRV, "Xrepeat:", 10,50,150,19, &tex->xrepeat, 1.0, 512.0, 0, 0, "Sets a repetition multiplier in the X direction"); - uiDefButS(block, NUM, B_TEXPRV, "Yrepeat:", 160,50,150,19, &tex->yrepeat, 1.0, 512.0, 0, 0, "Sets a repetition multiplier in the Y direction"); - } - else if(tex->extend==TEX_CHECKER) { - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, TEX_CHECKER_ODD, B_TEXPRV, "Odd", 10,50,100,19, &tex->flag, 0.0, 0.0, 0, 0, "Sets odd checker tiles"); - uiDefButBitS(block, TOG, TEX_CHECKER_EVEN, B_TEXPRV, "Even", 110,50,100,19, &tex->flag, 0.0, 0.0, 0, 0, "Sets even checker tiles"); - uiDefButF(block, NUM, B_TEXPRV, "Mortar:", 210,50,100,19, &tex->checkerdist, 0.0, 0.99, 0, 0, "Set checkers distance (like mortar)"); - } - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_TEXPRV, "MinX ", 10,28,150,19, &tex->cropxmin, -10.0, 10.0, 10, 0, "Sets minimum X value to crop Image"); - uiDefButF(block, NUM, B_TEXPRV, "MinY ", 10,8,150,19, &tex->cropymin, -10.0, 10.0, 10, 0, "Sets minimum Y value to crop Image"); - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_TEXPRV, "MaxX ", 160,28,150,19, &tex->cropxmax, -10.0, 10.0, 10, 0, "Sets maximum X value to crop Image"); - uiDefButF(block, NUM, B_TEXPRV, "MaxY ", 160,8,150,19, &tex->cropymax, -10.0, 10.0, 10, 0, "Sets maximum Y value to crop Image"); - uiBlockEndAlign(block); - } static void colorband_pos_cb(void *coba_v, void *unused_v) @@ -1594,7 +1876,7 @@ void do_worldbuts(unsigned short event) wrld= G.buts->lockpoin; if(wrld && wrld->mtex[(int)wrld->texact] ) { mtex= wrld->mtex[(int)wrld->texact]; - if(mtex->tex==0) { + if(mtex->tex==NULL) { error("No texture available"); } else { @@ -1606,7 +1888,7 @@ void do_worldbuts(unsigned short event) case B_WMTEXPASTE: wrld= G.buts->lockpoin; if(wrld && mtexcopied && mtexcopybuf.tex) { - if(wrld->mtex[(int)wrld->texact]==0 ) + if(wrld->mtex[(int)wrld->texact]==NULL ) wrld->mtex[(int)wrld->texact]= MEM_mallocN(sizeof(MTex), "mtex"); else if(wrld->mtex[(int)wrld->texact]->tex) wrld->mtex[(int)wrld->texact]->tex->id.us--; @@ -1641,7 +1923,7 @@ static void world_panel_mapto(World *wrld) uiSetButLock(wrld->id.lib!=0, "Can't edit library data"); mtex= wrld->mtex[ wrld->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); mtex->texco= TEXCO_VIEW; @@ -1707,7 +1989,7 @@ static void world_panel_texture(World *wrld) uiBlockEndAlign(block); mtex= wrld->mtex[ wrld->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); mtex->texco= TEXCO_VIEW; @@ -1984,7 +2266,7 @@ void do_lampbuts(unsigned short event) la= G.buts->lockpoin; if(la && la->mtex[(int)la->texact] ) { mtex= la->mtex[(int)la->texact]; - if(mtex->tex==0) { + if(mtex->tex==NULL) { error("No texture available"); } else { @@ -1996,7 +2278,7 @@ void do_lampbuts(unsigned short event) case B_LMTEXPASTE: la= G.buts->lockpoin; if(la && mtexcopied && mtexcopybuf.tex) { - if(la->mtex[(int)la->texact]==0 ) + if(la->mtex[(int)la->texact]==NULL ) la->mtex[(int)la->texact]= MEM_mallocN(sizeof(MTex), "mtex"); else if(la->mtex[(int)la->texact]->tex) la->mtex[(int)la->texact]->tex->id.us--; @@ -2026,7 +2308,7 @@ static void lamp_panel_mapto(Object *ob, Lamp *la) uiSetButLock(la->id.lib!=0, "Can't edit library data"); mtex= la->mtex[ la->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); mtex->texco= TEXCO_VIEW; @@ -2085,7 +2367,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) uiBlockEndAlign(block); mtex= la->mtex[ la->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); mtex->texco= TEXCO_VIEW; @@ -2233,7 +2515,7 @@ static void lamp_panel_spot(Object *ob, Lamp *la) if(la->area_shape==LA_AREA_CUBE) uiDefButS(block, NUM,0,"Samples:", 100,160,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp x samp)"); - if ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX)) { uiDefButS(block, NUM,0,"SamplesX:", 100,180,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of X samples taken extra"); uiDefButS(block, NUM,0,"SamplesY:", 100,160,200,19, &la->ray_sampy, 1.0, 16.0, 100, 0, "Sets the amount of Y samples taken extra"); if(la->area_shape==LA_AREA_BOX) @@ -2361,16 +2643,16 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) //uiDefButS(block, MENU, B_LAMPREDRAW, "Shape %t|Square %x0|Rect %x1|Cube %x2|Box %x3", uiDefButS(block, MENU, B_LAMPREDRAW, "Shape %t|Square %x0|Rect %x1", 10, 150, 100, 19, &la->area_shape, 0,0,0,0, "Sets area light shape"); - if ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX){ + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX)){ uiDefButF(block, NUM,B_LAMPREDRAW,"SizeX ", 10,130,100,19, &la->area_size, 0.01, 100.0, 10, 0, "Area light size X, doesn't affect energy amount"); uiDefButF(block, NUM,B_LAMPREDRAW,"SizeY ", 10,110,100,19, &la->area_sizey, 0.01, 100.0, 10, 0, "Area light size Y, doesn't affect energy amount"); } if(la->area_shape==LA_AREA_BOX) uiDefButF(block, NUM,B_LAMPREDRAW,"SizeZ ", 10,90,100,19, &la->area_sizez, 0.01, 100.0, 10, 0, "Area light size Z, doesn't affect energy amount"); - if ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_CUBE) + if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_CUBE)) uiDefButF(block, NUM,B_LAMPREDRAW,"Size ", 10,130,100,19, &la->area_size, 0.01, 100.0, 10, 0, "Area light size, doesn't affect energy amount"); } - else if ELEM(la->type, LA_LOCAL, LA_SPOT) { + else if( ELEM(la->type, LA_LOCAL, LA_SPOT)) { uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitS(block, TOG, LA_QUAD, B_LAMPPRV,"Quad", 10,150,100,19,&la->mode, 0, 0, 0, 0, "Uses inverse quadratic proportion for light attenuation"); uiDefButBitS(block, TOG, LA_SPHERE, REDRAWVIEW3D,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); @@ -2396,7 +2678,7 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiDefButF(block, COL, B_LAMPPRV, "", 120,52,180,24, &la->r, 0, 0, 0, B_COLLAMP, ""); uiBlockBeginAlign(block); - if ELEM(la->type, LA_LOCAL, LA_SPOT) { + if (ELEM(la->type, LA_LOCAL, LA_SPOT)) { uiDefButF(block, NUMSLI,B_LAMPPRV,"Quad1 ", 120,30,180,19,&la->att1, 0.0, 1.0, 0, 0, "Set the linear distance attenuatation for a quad lamp"); uiDefButF(block, NUMSLI,B_LAMPPRV,"Quad2 ", 120,10,180,19,&la->att2, 0.0, 1.0, 0, 0, "Set the quadratic distance attenuatation for a quad lamp"); } @@ -2561,7 +2843,7 @@ void do_matbuts(unsigned short event) case B_MTEXCOPY: if(ma && ma->mtex[(int)ma->texact] ) { mtex= ma->mtex[(int)ma->texact]; - if(mtex->tex==0) { + if(mtex->tex==NULL) { error("No texture available"); } else { @@ -2572,7 +2854,7 @@ void do_matbuts(unsigned short event) break; case B_MTEXPASTE: if(ma && mtexcopied && mtexcopybuf.tex) { - if(ma->mtex[(int)ma->texact]==0 ) + if(ma->mtex[(int)ma->texact]==NULL ) ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); else if(ma->mtex[(int)ma->texact]->tex) ma->mtex[(int)ma->texact]->tex->id.us--; @@ -2657,7 +2939,7 @@ static void material_panel_map_to(Material *ma) if(uiNewPanel(curarea, block, "Map To", "Material", 1600, 0, 318, 204)==0) return; mtex= ma->mtex[ ma->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); } @@ -2734,7 +3016,7 @@ static void material_panel_map_input(Object *ob, Material *ma) if(uiNewPanel(curarea, block, "Map Input", "Material", 1280, 0, 318, 204)==0) return; mtex= ma->mtex[ ma->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); } @@ -2835,14 +3117,14 @@ static void material_panel_texture(Material *ma) uiBlockSetCol(block, TH_AUTO); mtex= ma->mtex[ ma->texact ]; - if(mtex==0) { + if(mtex==NULL) { mtex= &emptytex; default_mtex(mtex); } /* TEXTUREBLOK SELECT */ uiBlockSetCol(block, TH_BUT_SETTING2); - if(G.main->tex.first==0) + if(G.main->tex.first==NULL) id= NULL; else id= (ID*) mtex->tex; @@ -3388,7 +3670,7 @@ void material_panels() MTex *mtex; Object *ob= OBACT; - if(ob==0) return; + if(ob==NULL) return; // type numbers are ordered if((ob->typetype) { @@ -3537,8 +3819,8 @@ void texture_panels() switch(tex->type) { case TEX_IMAGE: - texture_panel_image(tex); - texture_panel_image1(tex); + texture_panel_image(&tex->ima, &tex->iuser); + texture_panel_image_map(tex); break; case TEX_ENVMAP: texture_panel_envmap(tex); @@ -3589,7 +3871,7 @@ void radio_panels() int flag; rad= G.scene->radio; - if(rad==0) { + if(rad==NULL) { add_radio(); rad= G.scene->radio; } diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 7e77432158e..48a99168923 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -1,15 +1,12 @@ /** * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * 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 @@ -25,9 +22,9 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation, 2002-2006 * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #include @@ -56,6 +53,7 @@ #include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" @@ -99,8 +97,10 @@ #include "BIF_transform.h" #include "BSE_drawipo.h" +#include "BSE_drawview.h" #include "BSE_filesel.h" #include "BSE_headerbuttons.h" +#include "BSE_node.h" #include "BSE_trans_types.h" #include "BSE_view.h" @@ -118,26 +118,24 @@ static unsigned char *alloc_alpha_clone_image(int *width, int *height) { Brush *brush = G.scene->toolsettings->imapaint.brush; - Image *image; + ImBuf *ibuf; unsigned int size, alpha; unsigned char *rect, *cp; if(!brush || !brush->clone.image) return NULL; - image= brush->clone.image; - if(!image->ibuf) - load_image(image, IB_rect, G.sce, G.scene->r.cfra); + ibuf= BKE_image_get_ibuf(brush->clone.image, NULL); - if(!image->ibuf || !image->ibuf->rect) + if(!ibuf || !ibuf->rect) return NULL; - rect= MEM_dupallocN(image->ibuf->rect); + rect= MEM_dupallocN(ibuf->rect); if(!rect) return NULL; - *width= image->ibuf->x; - *height= image->ibuf->y; + *width= ibuf->x; + *height= ibuf->y; size= (*width)*(*height); alpha= (unsigned char)255*brush->clone.alpha; @@ -190,11 +188,13 @@ void calc_image_view(SpaceImage *sima, char mode) if(image_preview_active(curarea, &xim, &yim)); else if(sima->image) { - if(sima->image->ibuf) { - xim= sima->image->ibuf->x; - yim= sima->image->ibuf->y; + ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + + if(ibuf) { + xim= ibuf->x; + yim= ibuf->y; } - else if( BLI_streq(sima->image->id.name+2, "Render Result") ) { + else if( sima->image->type==IMA_TYPE_R_RESULT ) { /* not very important, just nice */ xim= (G.scene->r.xsch*G.scene->r.size)/100; yim= (G.scene->r.ysch*G.scene->r.size)/100; @@ -246,24 +246,8 @@ void what_image(SpaceImage *sima) if(sima->mode==SI_TEXTURE) { - if(sima->image && BLI_streq(sima->image->id.name+2, "Render Result")) { - if(sima->image->ibuf==NULL) { - RenderResult rres; - - /* make ibuf if needed, and initialize it */ - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); - if(rres.rectf || rres.rect32) { - ImBuf *ibuf= sima->image->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0); - - ibuf->x= rres.rectx; - ibuf->y= rres.recty; - ibuf->rect= rres.rect32; - ibuf->rect_float= rres.rectf; - - sima->image->ok= 1; - } - } - } + /* viewer overrides faceselect */ + if(sima->image && sima->image->source==IMA_SRC_VIEWER); else if((G.f & G_FACESELECT)) { sima->image= NULL; @@ -301,11 +285,11 @@ void image_changed(SpaceImage *sima, int dotile) if(G.f & G_FACESELECT) { - /* exception images, name rules are actually weak... */ + /* skip assigning these procedural images... */ if(sima->image) { - if(BLI_streq(sima->image->id.name+2, "Render Result")) + if(sima->image->type==IMA_TYPE_R_RESULT) return; - if(BLI_streq(sima->image->id.name+2, "Composite")) + if(sima->image->type==IMA_TYPE_COMPOSITE) return; } @@ -740,26 +724,25 @@ static void draw_image_view_tool(void) /* ************ panel stuff ************* */ -// button define is local, only events defined here possible -#define B_TRANS_IMAGE 1 - /* is used for both read and write... */ -static void image_editvertex_buts(uiBlock *block) +void image_editvertex_buts(uiBlock *block) { static float ocent[2]; float cent[2]= {0.0, 0.0}; - int imx, imy; + int imx= 256, imy= 256; int i, nactive= 0, step, digits; Mesh *me; if( is_uv_tface_editing_allowed_silent()==0 ) return; me= get_mesh(OBACT); - if (G.sima->image && G.sima->image->ibuf) { - imx= G.sima->image->ibuf->x; - imy= G.sima->image->ibuf->y; - } else - imx= imy= 256; + if (G.sima->image) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + if(ibuf) { + imx= ibuf->x; + imy= ibuf->y; + } + } for (i=0; itotface; i++) { MFace *mf= &((MFace*) me->mface)[i]; @@ -863,174 +846,77 @@ static void image_editvertex_buts(uiBlock *block) } } - -void do_imagebuts(unsigned short event) +void image_info(Image *ima, ImBuf *ibuf, char *str) { - ToolSettings *settings= G.scene->toolsettings; - - switch(event) { - case B_TRANS_IMAGE: - image_editvertex_buts(NULL); - break; - - case B_SIMAGEDRAW: - if(G.f & G_FACESELECT) { - make_repbind(G.sima->image); - image_changed(G.sima, 1); - } - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); - break; - - case B_SIMAGEDRAW1: - image_changed(G.sima, 2); /* 2: only tileflag */ - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); - break; - - case B_TWINANIM: - { - Image *ima; - int nr; - - ima = G.sima->image; - if (ima) { - if(ima->flag & IMA_TWINANIM) { - nr= ima->xrep*ima->yrep; - if(ima->twsta>=nr) ima->twsta= 1; - if(ima->twend>=nr) ima->twend= nr-1; - if(ima->twsta>ima->twend) ima->twsta= 1; - allqueue(REDRAWIMAGE, 0); - } - } - } - break; - - case B_SIMACLONEBROWSE: - if (settings->imapaint.brush) - if (brush_clone_image_set_nr(settings->imapaint.brush, G.sima->menunr)) - allqueue(REDRAWIMAGE, 0); - break; - - case B_SIMACLONEDELETE: - if (settings->imapaint.brush) - if (brush_clone_image_delete(settings->imapaint.brush)) - allqueue(REDRAWIMAGE, 0); - break; + int ofs= 0; + + str[0]= 0; + + if(ima==NULL) return; + if(ibuf==NULL) { + sprintf(str, "Can not get an image"); + return; + } + + if(ima->source==IMA_SRC_MOVIE) { + ofs= sprintf(str, "Movie "); + if(ima->anim) + ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim)); + } + else + ofs= sprintf(str, "Image "); - case B_SIMABRUSHCHANGE: - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWBUTSEDIT, 0); - break; - - case B_SIMACURVES: - curvemapping_do_image(G.sima->cumap, G.sima->image); - allqueue(REDRAWIMAGE, 0); - break; - - case B_SIMARANGE: - curvemapping_set_black_white(G.sima->cumap, NULL, NULL); - curvemapping_do_image(G.sima->cumap, G.sima->image); - allqueue(REDRAWIMAGE, 0); - break; + ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y); - case B_SIMABRUSHBROWSE: - if(G.sima->menunr==-2) { - activate_databrowse((ID*)settings->imapaint.brush, ID_BR, 0, B_SIMABRUSHBROWSE, &G.sima->menunr, do_global_buttons); - break; - } - else if(G.sima->menunr < 0) break; - - if(brush_set_nr(&settings->imapaint.brush, G.sima->menunr)) { - BIF_undo_push("Browse Brush"); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWIMAGE, 0); - } - break; - case B_SIMABRUSHDELETE: - if(brush_delete(&settings->imapaint.brush)) { - BIF_undo_push("Unlink Brush"); - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWBUTSEDIT, 0); - } - break; - case B_KEEPDATA: - brush_toggle_fake_user(settings->imapaint.brush); - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWBUTSEDIT, 0); - break; - case B_SIMABRUSHLOCAL: - if(settings->imapaint.brush && settings->imapaint.brush->id.lib) { - if(okee("Make local")) { - make_local_brush(settings->imapaint.brush); - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWBUTSEDIT, 0); - } - } - break; - case B_SIMABTEXBROWSE: - if(settings->imapaint.brush) { - Brush *brush= settings->imapaint.brush; - - if(G.sima->menunr==-2) { - MTex *mtex= brush->mtex[brush->texact]; - ID *id= (ID*)((mtex)? mtex->tex: NULL); - activate_databrowse(id, ID_TE, 0, B_SIMABTEXBROWSE, &G.sima->menunr, do_global_buttons); - break; - } - else if(G.sima->menunr < 0) break; - - if(brush_texture_set_nr(brush, G.sima->menunr)) { - BIF_undo_push("Browse Brush Texture"); - allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWIMAGE, 0); - } + if(ibuf->rect_float) { + if(ibuf->channels!=4) { + sprintf(str+ofs, "%d float channel(s)", ibuf->channels); } - break; - case B_SIMABTEXDELETE: - if(settings->imapaint.brush) { - if (brush_texture_delete(settings->imapaint.brush)) { - BIF_undo_push("Unlink Brush Texture"); - allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWIMAGE, 0); - } - } - break; + else if(ibuf->depth==32) + strcat(str, " RGBA float"); + else + strcat(str, " RGB float"); } + else { + if(ibuf->depth==32) + strcat(str, " RGBA byte"); + else + strcat(str, " RGB byte"); + } + if(ibuf->zbuf || ibuf->zbuf_float) + strcat(str, " + Z"); + } static void image_panel_properties(short cntrl) // IMAGE_HANDLER_PROPERTIES { uiBlock *block; - + block= uiNewBlock(&curarea->uiblocks, "image_panel_properties", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(IMAGE_HANDLER_PROPERTIES); // for close and esc if(uiNewPanel(curarea, block, "Properties", "Image", 10, 10, 318, 204)==0) return; + + uiblock_image_panel(block, &G.sima->image, &G.sima->iuser, B_REDR, B_REDR); - if (G.sima->image && G.sima->image->ibuf) { - ImBuf *ibuf= G.sima->image->ibuf; - char str[64]; +} - sprintf(str, "Image: size %d x %d", ibuf->x, ibuf->y); - if(ibuf->rect_float) { - if(ibuf->depth==32) - strcat(str, " RGBA float"); - else - strcat(str, " RGB float"); - } - else { - if(ibuf->depth==32) - strcat(str, " RGBA byte"); - else - strcat(str, " RGB byte"); - } - if(ibuf->zbuf || ibuf->zbuf_float) - strcat(str, " + Z"); +static void image_panel_game_properties(short cntrl) // IMAGE_HANDLER_GAME_PROPERTIES +{ + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "image_panel_game_properties", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(IMAGE_HANDLER_GAME_PROPERTIES); // for close and esc + if(uiNewPanel(curarea, block, "Game Properties", "Image", 10, 10, 318, 204)==0) + return; + + if (ibuf) { + char str[128]; + image_info(G.sima->image, ibuf, str); uiDefBut(block, LABEL, B_NOP, str, 10,180,300,19, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); @@ -1050,7 +936,7 @@ static void image_panel_properties(short cntrl) // IMAGE_HANDLER_PROPERTIES image_editvertex_buts(block); } -static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES +static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PAINT { /* B_SIMABRUSHCHANGE only redraws and eats the mouse messages */ /* so that LEFTMOUSE does not 'punch' through the floating panel */ @@ -1135,7 +1021,7 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES #endif } -static void image_panel_curves_reset(void *cumap_v, void *unused) +static void image_panel_curves_reset(void *cumap_v, void *ibuf_v) { CurveMapping *cumap = cumap_v; int a; @@ -1148,14 +1034,15 @@ static void image_panel_curves_reset(void *cumap_v, void *unused) curvemapping_set_black_white(cumap, NULL, NULL); curvemapping_changed(cumap, 0); - curvemapping_do_image(cumap, G.sima->image); + curvemapping_do_ibuf(cumap, ibuf_v); allqueue(REDRAWIMAGE, 0); } -static void image_panel_curves(short cntrl) // IMAGE_HANDLER_PROPERTIES +static void image_panel_curves(short cntrl) // IMAGE_HANDLER_CURVES { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); uiBlock *block; uiBut *bt; @@ -1165,7 +1052,7 @@ static void image_panel_curves(short cntrl) // IMAGE_HANDLER_PROPERTIES if(uiNewPanel(curarea, block, "Curves", "Image", 10, 450, 318, 204)==0) return; - if (G.sima->image && G.sima->image->ibuf) { + if (ibuf) { rctf rect; if(G.sima->cumap==NULL) @@ -1176,7 +1063,7 @@ static void image_panel_curves(short cntrl) // IMAGE_HANDLER_PROPERTIES curvemap_buttons(block, G.sima->cumap, 'c', B_SIMACURVES, B_SIMAGEDRAW, &rect); bt=uiDefBut(block, BUT, B_SIMARANGE, "Reset", 10, 160, 90, 19, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves"); - uiButSetFunc(bt, image_panel_curves_reset, G.sima->cumap, NULL); + uiButSetFunc(bt, image_panel_curves_reset, G.sima->cumap, ibuf); uiBlockBeginAlign(block); uiDefButF(block, NUM, B_SIMARANGE, "Min R:", 10, 120, 90, 19, G.sima->cumap->black, -1000.0f, 1000.0f, 10, 2, "Black level"); @@ -1339,6 +1226,9 @@ static void image_blockhandlers(ScrArea *sa) case IMAGE_HANDLER_PROPERTIES: image_panel_properties(sima->blockhandler[a+1]); break; + case IMAGE_HANDLER_GAME_PROPERTIES: + image_panel_game_properties(sima->blockhandler[a+1]); + break; case IMAGE_HANDLER_PAINT: image_panel_paint(sima->blockhandler[a+1]); break; @@ -1355,6 +1245,53 @@ static void image_blockhandlers(ScrArea *sa) uiDrawBlocksPanels(sa, 0); } +void imagespace_composite_flipbook(ScrArea *sa) +{ + SpaceImage *sima= sa->spacedata.first; + ImBuf *ibuf; + int cfrao= G.scene->r.cfra; + int sfra, efra; + + if(sa->spacetype!=SPACE_IMAGE) + return; + if(sima->iuser.frames<2) + return; + if(G.scene->nodetree==NULL) + return; + + sfra= sima->iuser.sfra; + efra= sima->iuser.sfra + sima->iuser.frames-1; + G.scene->nodetree->test_break= blender_test_break; + + for(G.scene->r.cfra=sfra; G.scene->r.cfra<=efra; G.scene->r.cfra++) { + + set_timecursor(CFRA); + + BKE_image_all_free_anim_ibufs(CFRA); + ntreeCompositTagAnimated(G.scene->nodetree); + ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, G.scene->r.cfra!=cfrao); /* 1 is no previews */ + + force_draw(0); + + ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + /* save memory in flipbooks */ + if(ibuf) + imb_freerectfloatImBuf(ibuf); + + if(blender_test_break()) + break; + } + G.scene->nodetree->test_break= NULL; + waitcursor(0); + + play_anim(0); + + allqueue(REDRAWNODE, 1); + allqueue(REDRAWIMAGE, 1); + + G.scene->r.cfra= cfrao; +} + static void imagespace_grid(SpaceImage *sima) { float gridsize, gridstep= 1.0f/32.0f; @@ -1548,8 +1485,9 @@ static void imagewindow_draw_renderinfo(ScrArea *sa) SpaceImage *sima= sa->spacedata.first; rcti rect; float colf[3]; + char *str= sima->showspare?sima->info_spare:sima->info_str; - if(sima->info_str==NULL) + if(str==NULL) return; rect= sa->winrct; @@ -1564,7 +1502,11 @@ static void imagewindow_draw_renderinfo(ScrArea *sa) BIF_ThemeColor(TH_TEXT_HI); glRasterPos2i(12, 5); - BMF_DrawString(G.fonts, sima->info_str); + if(sima->showspare) { + BMF_DrawString(G.fonts, "(Previous)"); + glRasterPos2i(72, 5); + } + BMF_DrawString(G.fonts, str); } void drawimagespace(ScrArea *sa, void *spacedata) @@ -1575,7 +1517,7 @@ void drawimagespace(ScrArea *sa, void *spacedata) float col[3]; unsigned int *rect; float x1, y1; - short sx, sy, dx, dy, show_render= 0; + short sx, sy, dx, dy, show_render= 0, show_viewer= 0; /* If derived data is used then make sure that object * is up-to-date... might not be the case because updates @@ -1593,24 +1535,33 @@ void drawimagespace(ScrArea *sa, void *spacedata) bwin_clear_viewmat(sa->win); /* clear buttons view */ glLoadIdentity(); - if(sima->image && BLI_streq(sima->image->id.name+2, "Render Result") ) - show_render= 1; - + if(sima->image && sima->image->source==IMA_SRC_VIEWER) { + show_viewer= 1; + if(sima->image->type==IMA_TYPE_R_RESULT) + show_render= 1; + } what_image(sima); if(sima->image) { - if(sima->image->ibuf==NULL && show_render==0) { - load_image(sima->image, IB_rect, G.sce, G.scene->r.cfra); - scrarea_queue_headredraw(sa); /* update header for image options */ - } - tag_image_time(sima->image); - ibuf= sima->image->ibuf; + /* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */ + if(sima->image->type==IMA_TYPE_COMPOSITE) { + ImageUser *iuser= ntree_get_active_iuser(G.scene->nodetree); + if(iuser) { + BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0); + G.sima->iuser= *iuser; + } + } + /* and we check for spare */ + if(sima->image->type==IMA_TYPE_R_RESULT && sima->showspare) + ibuf= sima->spare; + else + ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); } if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { imagespace_grid(sima); - if(show_render==0) + if(show_viewer==0) draw_tfaces(); } else { @@ -1706,14 +1657,16 @@ void drawimagespace(ScrArea *sa, void *spacedata) if(sima->flag & SI_SHOW_ALPHA) { if(ibuf->rect) sima_draw_alpha_pixels(x1, y1, ibuf->x, ibuf->y, ibuf->rect); - else if(ibuf->rect_float) + else if(ibuf->rect_float && ibuf->channels==4) sima_draw_alpha_pixelsf(x1, y1, ibuf->x, ibuf->y, ibuf->rect_float); } else if(sima->flag & SI_SHOW_ZBUF) { if(ibuf->zbuf) sima_draw_zbuf_pixels(x1, y1, ibuf->x, ibuf->y, ibuf->zbuf); - else + else if(ibuf->zbuf_float) sima_draw_zbuffloat_pixels(x1, y1, ibuf->x, ibuf->y, ibuf->zbuf_float); + else if(ibuf->channels==1) + sima_draw_zbuffloat_pixels(x1, y1, ibuf->x, ibuf->y, ibuf->rect_float); } else { if(sima->flag & SI_USE_ALPHA) { @@ -1725,11 +1678,14 @@ void drawimagespace(ScrArea *sa, void *spacedata) /* detect if we need to redo the curve map. ibuf->rect is zero for compositor and render results after change convert to 32 bits always... drawing float rects isnt supported well (atis) + + NOTE: if float buffer changes, we have to manually remove the rect */ + if(ibuf->rect_float) { if(ibuf->rect==NULL) { if(image_curves_active(sa)) - curvemapping_do_image(G.sima->cumap, G.sima->image); + curvemapping_do_ibuf(G.sima->cumap, ibuf); else IMB_rect_from_float(ibuf); } @@ -1770,7 +1726,7 @@ void drawimagespace(ScrArea *sa, void *spacedata) glPixelZoom(1.0, 1.0); - if(show_render==0) + if(show_viewer==0) draw_tfaces(); } @@ -1828,7 +1784,9 @@ static void image_zoom_set_factor(float zoomfac) width= 256; height= 256; if (sima->image) { - if (sima->image->ibuf) { + ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + + if (ibuf) { float xim, yim; /* I know a bit weak... but preview uses not actual image size */ if(image_preview_active(curarea, &xim, &yim)) { @@ -1836,8 +1794,8 @@ static void image_zoom_set_factor(float zoomfac) height= (int) yim; } else { - width= sima->image->ibuf->x; - height= sima->image->ibuf->y; + width= ibuf->x; + height= ibuf->y; } } } @@ -1938,18 +1896,19 @@ void image_viewzoom(unsigned short event, int invert) */ void image_home(void) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); int width, height, imgwidth, imgheight; float zoomX, zoomY; if (curarea->spacetype != SPACE_IMAGE) return; - if ((G.sima->image == NULL) || (G.sima->image->ibuf == NULL)) { + if (ibuf == NULL) { imgwidth = 256; imgheight = 256; } else { - imgwidth = G.sima->image->ibuf->x; - imgheight = G.sima->image->ibuf->y; + imgwidth = ibuf->x; + imgheight = ibuf->y; } /* Check if the image will fit in the image with zoom==1 */ @@ -1977,15 +1936,16 @@ void image_home(void) void image_viewcentre(void) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); float size, min[2], max[2], d[2], xim=256.0f, yim=256.0f; if( is_uv_tface_editing_allowed()==0 ) return; if (!minmax_tface_uv(min, max)) return; - if(G.sima->image && G.sima->image->ibuf) { - xim= G.sima->image->ibuf->x; - yim= G.sima->image->ibuf->y; + if(ibuf) { + xim= ibuf->x; + yim= ibuf->y; } G.sima->xof= (int) (((min[0] + max[0])*0.5f - 0.5f)*xim); @@ -2090,14 +2050,6 @@ static void imagewindow_progress_display_cb(RenderResult *rr, volatile rcti *rec if (image_area) { - if(rect==NULL) { - SpaceImage *sima= image_area->spacedata.first; - - /* this enforces reading correct buffer in what_image(), renderlayers/scenes/compo/sequences... */ - IMB_freeImBuf(sima->image->ibuf); - sima->image->ibuf= NULL; - } - imagewindow_progress(image_area, rr, rect); /* no screen_swapbuffers, prevent any other window to draw */ @@ -2153,7 +2105,7 @@ static ScrArea *biggest_area(void) make a new temp fullscreen area with Image Window */ -static ScrArea *imagewindow_set_render_display(void) +static ScrArea *find_area_showing_r_result(void) { ScrArea *sa; SpaceImage *sima; @@ -2162,11 +2114,20 @@ static ScrArea *imagewindow_set_render_display(void) for(sa=G.curscreen->areabase.first; sa; sa= sa->next) { if(sa->spacetype==SPACE_IMAGE) { sima= sa->spacedata.first; - - if(sima->image && BLI_streq(sima->image->id.name+2, "Render Result") ) + if(sima->image && sima->image->type==IMA_TYPE_R_RESULT) break; } } + return sa; +} + +static ScrArea *imagewindow_set_render_display(void) +{ + ScrArea *sa; + SpaceImage *sima; + + sa= find_area_showing_r_result(); + if(sa==NULL) { /* find largest open non-image area */ sa= biggest_non_image_area(); @@ -2193,21 +2154,7 @@ static ScrArea *imagewindow_set_render_display(void) sima= sa->spacedata.first; /* get the correct image, and scale it */ - sima->image = (Image *)find_id("IM", "Render Result"); - - if(sima->image==NULL) { - Image *ima= alloc_libblock(&G.main->image, ID_IM, "Render Result"); - strcpy(ima->name, "Render Result"); - ima->ok= 1; - ima->xrep= ima->yrep= 1; - sima->image= ima; - } - else if(sima->image->id.us==0) /* well... happens on reload, dunno yet what todo, imagewindow cannot be user when hidden*/ - id_us_plus(&sima->image->id); - - /* this enforces reading empty buffer in what_image(), so display is cleared */ - IMB_freeImBuf(sima->image->ibuf); - sima->image->ibuf= NULL; + sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); if(G.displaymode==R_DISPLAYSCREEN) { if(sa->full==0) { @@ -2260,7 +2207,7 @@ void imagewindow_toggle_render(void) if(sa->spacetype==SPACE_IMAGE) { SpaceImage *sima= sa->spacedata.first; - if(sima->image && BLI_streq(sima->image->id.name+2, "Render Result") ) + if(sima->image && sima->image->type==IMA_TYPE_R_RESULT) if(sima->flag & (SI_PREVSPACE|SI_FULLWINDOW)) break; } @@ -2292,7 +2239,6 @@ static void imagewindow_renderinfo_cb(RenderStats *rs) } } - void imagewindow_render_callbacks(Render *re) { RE_display_init_cb(re, imagewindow_init_display_cb); @@ -2301,3 +2247,53 @@ void imagewindow_render_callbacks(Render *re) RE_stats_draw_cb(re, imagewindow_renderinfo_cb); } +void imagewin_store_spare(void) +{ + ScrArea *sa= find_area_showing_r_result(); + + if(sa) { + ImBuf *ibuf; + SpaceImage *sima= sa->spacedata.first; + + if(sima->spare==NULL) + return; + + /* only store when it does not show spare */ + if(sima->showspare==0) + return; + sima->showspare= 0; + + /* free spare */ + IMB_freeImBuf(sima->spare); + + /* make a copy of render result */ + ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + sima->spare= IMB_dupImBuf(ibuf); + + BLI_strncpy(sima->info_spare, sima->info_str, RW_MAXTEXT); + + } +} + +/* context: in current image window? */ +void imagewindow_swap_render_rects(void) +{ + ScrArea *sa= find_area_showing_r_result(); + + if(sa) { + SpaceImage *sima= sa->spacedata.first; + ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + if(ibuf) { + + sima->showspare ^= 1; + + if(sima->spare==NULL) + sima->spare= IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0, 0); + if(sima->info_spare==NULL) + sima->info_spare= MEM_callocN(RW_MAXTEXT, "info str imagewin"); + + allqueue(REDRAWIMAGE, 0); + } + } +} + diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index c6b0a874ff4..94255384108 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -183,6 +183,7 @@ int set_tpage(MTFace *tface) static int alphamode= -1; static MTFace *lasttface= 0; Image *ima; + ImBuf *ibuf; unsigned int *rect=NULL, *bind; int tpx=0, tpy=0, tilemode, tileXRep,tileYRep; @@ -256,8 +257,7 @@ int set_tpage(MTFace *tface) tilemode= tface->mode & TF_TILES; tileXRep = 0; tileYRep = 0; - if (ima) - { + if (ima) { tileXRep = ima->xrep; tileYRep = ima->yrep; } @@ -265,18 +265,17 @@ int set_tpage(MTFace *tface) if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0; - if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep) - { + if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); - if(tilemode && ima!=0) + if(tilemode && ima!=NULL) glScalef(ima->xrep, ima->yrep, 1.0); glMatrixMode(GL_MODELVIEW); } - if(ima==0 || ima->ok==0) { + if(ima==NULL || ima->ok==0) { glDisable(GL_TEXTURE_2D); fCurtile= tface->tile; @@ -288,25 +287,21 @@ int set_tpage(MTFace *tface) return 0; } - if(ima->ibuf==0) { - load_image(ima, IB_rect, G.sce, G.scene->r.cfra); + ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf==NULL) { - if(ima->ibuf==0) { - ima->ok= 0; - - fCurtile= tface->tile; - fCurpage= 0; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - glDisable(GL_TEXTURE_2D); - return 0; - } + fCurtile= tface->tile; + fCurpage= 0; + fCurmode= tilemode; + fCurtileXRep = tileXRep; + fCurtileYRep = tileYRep; + + glDisable(GL_TEXTURE_2D); + return 0; } - if ((ima->ibuf->rect==NULL) && ima->ibuf->rect_float) - IMB_rect_from_float(ima->ibuf); + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe; else fCurtile= tface->tile; @@ -323,8 +318,8 @@ int set_tpage(MTFace *tface) if(*bind==0) { - fTexwindx= ima->ibuf->x/ima->xrep; - fTexwindy= ima->ibuf->y/ima->yrep; + fTexwindx= ibuf->x/ima->xrep; + fTexwindy= ibuf->y/ima->yrep; if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1; @@ -337,16 +332,16 @@ int set_tpage(MTFace *tface) tpx= fTexwindx; tpy= fTexwindy; - rect= ima->ibuf->rect + fTexwinsy*ima->ibuf->x + fTexwinsx; + rect= ibuf->rect + fTexwinsy*ibuf->x + fTexwinsx; } } else { bind= &ima->bindcode; if(*bind==0) { - tpx= ima->ibuf->x; - tpy= ima->ibuf->y; - rect= ima->ibuf->rect; + tpx= ibuf->x; + tpy= ibuf->y; + rect= ibuf->rect; } } @@ -367,7 +362,7 @@ int set_tpage(MTFace *tface) tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); for (y=0; yibuf->x]; + unsigned int *rectrow= &rect[y*ibuf->x]; unsigned int *tilerectrow= &tilerect[y*rectw]; memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); @@ -422,8 +417,6 @@ int set_tpage(MTFace *tface) } else glBindTexture( GL_TEXTURE_2D, *bind); - tag_image_time(ima); - glEnable(GL_TEXTURE_2D); fCurpage= ima; @@ -436,8 +429,10 @@ int set_tpage(MTFace *tface) void update_realtime_image(Image *ima, int x, int y, int w, int h) { - if (ima->repbind || get_mipmap() || !ima->bindcode || !ima->ibuf || - (!is_pow2(ima->ibuf->x) || !is_pow2(ima->ibuf->y)) || + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if (ima->repbind || get_mipmap() || !ima->bindcode || !ibuf || + (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || (w == 0) || (h == 0)) { /* these special cases require full reload still */ free_realtime_image(ima); @@ -447,17 +442,17 @@ void update_realtime_image(Image *ima, int x, int y, int w, int h) int skip_pixels = glaGetOneInteger(GL_UNPACK_SKIP_PIXELS); int skip_rows = glaGetOneInteger(GL_UNPACK_SKIP_ROWS); - if ((ima->ibuf->rect==NULL) && ima->ibuf->rect_float) - IMB_rect_from_float(ima->ibuf); + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glPixelStorei(GL_UNPACK_ROW_LENGTH, ima->ibuf->x); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); glPixelStorei(GL_UNPACK_SKIP_ROWS, y); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ima->ibuf->rect); + GL_UNSIGNED_BYTE, ibuf->rect); glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); @@ -536,7 +531,9 @@ void texpaint_enable_mipmap(void) void make_repbind(Image *ima) { - if(ima==0 || ima->ibuf==0) return; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf==NULL) return; if(ima->repbind) { glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); @@ -1050,7 +1047,7 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt) float v1[3], v2[3], v3[3], v4[3]; char string[MAX_PROPSTRING]; int characters, index; - Image *ima; + ImBuf *ibuf; float curpos; if (badtex) @@ -1068,8 +1065,8 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt) set_property_valstr(prop, string); characters = strlen(string); - ima = tface->tpage; - if (ima == NULL) { + ibuf= BKE_image_get_ibuf(tface->tpage, NULL); + if (ibuf == NULL) { characters = 0; } @@ -1092,7 +1089,7 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt) // space starts at offset 1 // character = character - ' ' + 1; - matrixGlyph(ima->ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + matrixGlyph(ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); movex+= curpos; if (tface->mode & TF_OBCOL) glColor3ubv(obcol); diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index d23f86ce4df..831387de931 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -647,7 +647,7 @@ static void node_shader_set_butfunc(bNodeType *ntype) } } -/* ****************** BUTTON CALLBACKS FOR COMPOSIT NODES ***************** */ +/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */ @@ -670,6 +670,7 @@ static void node_browse_image_cb(void *ntree_v, void *node_v) BLI_strncpy(node->name, node->id->name+2, 21); NodeTagChanged(ntree, node); + BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE); addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr); } node->menunr= 0; @@ -679,24 +680,57 @@ static void node_active_cb(void *ntree_v, void *node_v) { nodeSetActive(ntree_v, node_v); } -static void node_image_anim_cb(void *node_v, void *unused) +static void node_image_type_cb(void *node_v, void *unused) { - bNode *node= node_v; - NodeImageAnim *nia; - if(node->storage) { - MEM_freeN(node->storage); - node->storage= NULL; - } - else { - nia= node->storage= MEM_callocN(sizeof(NodeImageAnim), "node image anim"); - nia->sfra= nia->nr= 1; - } allqueue(REDRAWNODE, 1); } +static char *node_image_type_pup(void) +{ + char *str= MEM_mallocN(256, "image type pup"); + int a; + + str[0]= 0; + + a= sprintf(str, "Image Type %%t|"); + a+= sprintf(str+a, " Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DEHLT); + a+= sprintf(str+a, " Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE); + a+= sprintf(str+a, " Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL); + a+= sprintf(str+a, " Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1); + + return str; +} + +/* copy from buttons_shading.c */ +static char *layer_menu(RenderResult *rr) +{ + RenderLayer *rl; + int len= 40 + 40*BLI_countlist(&rr->layers); + short a, nr; + char *str= MEM_callocN(len, "menu layers"); + + strcpy(str, "Layer %t"); + a= strlen(str); + for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) { + a+= sprintf(str+a, "|%s %%x%d", rl->name, nr); + } + + return str; +} + +static void image_layer_cb(void *ima_v, void *iuser_v) +{ + + ntreeCompositForceHidden(G.scene->nodetree); + BKE_image_multilayer_index(ima_v, iuser_v); + allqueue(REDRAWNODE, 0); +} + static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { + ImageUser *iuser= node->storage; + if(block) { uiBut *bt; short dy= (short)butr->ymax-19; @@ -706,7 +740,7 @@ static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *nod uiBlockSetCol(block, TH_BUT_SETTING2); /* browse button */ - IDnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); + IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); node->menunr= 0; bt= uiDefButS(block, MENU, B_NOP, strp, butr->xmin, dy, 19, 19, @@ -723,44 +757,82 @@ static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *nod uiBlockSetCol(block, TH_AUTO); } else { - /* name button */ - short width= (short)(butr->xmax-butr->xmin-38.0f); - bt= uiDefBut(block, TEX, B_NOP, "IMA:", - butr->xmin+19, dy, width, 19, + /* name button + type */ + Image *ima= (Image *)node->id; + short xmin= (short)butr->xmin, xmax= (short)butr->xmax; + short width= xmax - xmin - 45; + short icon= ICON_IMAGE_DEHLT; + + if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE; + else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL; + else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1; + + bt= uiDefBut(block, TEX, B_NOP, "IM:", + xmin+19, dy, width, 19, node->id->name+2, 0.0, 19.0, 0, 0, "Image name"); uiButSetFunc(bt, node_ID_title_cb, node, NULL); - bt= uiDefIconBut(block, BUT, B_NOP, ICON_SEQUENCE, - butr->xmax-19, dy, 19, 19, - node->id->name+2, 0.0, 19.0, 0, 0, "Enable/Disable Image animation"); - uiButSetFunc(bt, node_image_anim_cb, node, NULL); - } - if(node->storage) { - NodeImageAnim *nia= node->storage; - short width= (short)(butr->xmax-butr->xmin)/2; - dy-= 19; - uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:", - butr->xmin, dy, width, 19, - &nia->frames, 0.0, 10000.0, 0, 0, "Amount of images used in animation"); - uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:", - butr->xmin+width, dy, width, 19, - &nia->sfra, 1.0, 10000.0, 0, 0, "Start frame of animation"); - dy-= 19; - uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "First:", - butr->xmin, dy, width, 19, - &nia->nr, 0.0, 10000.0, 0, 0, "Number in image name, used as first in animation"); - uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Cycl", - butr->xmin+width, dy, width-19, 19, - &nia->cyclic, 0.0, 0.0, 0, 0, "Make animation go cyclic"); - bt= uiDefIconButC(block, TOG, B_NODE_EXEC+node->nr, ICON_SEQUENCE, - butr->xmax-19, dy, 19, 19, - &nia->movie, 0.0, 19.0, 0, 0, "Enable/Disable reading Image from Movie file"); + /* buffer type option */ + strp= node_image_type_pup(); + bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp, + xmax-26, dy, 26, 19, + &ima->source, 0.0, 19.0, 0, 0, "Image type"); + uiButSetFunc(bt, node_image_type_cb, node, ima); + MEM_freeN(strp); + if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) { + width= (xmax-xmin)/2; + + dy-= 19; + uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:", + xmin, dy, width, 19, + &iuser->frames, 0.0, 10000.0, 0, 0, "Amount of images used in animation"); + uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:", + xmin+width, dy, width, 19, + &iuser->sfra, 1.0, 10000.0, 0, 0, "Start frame of animation"); + dy-= 19; + uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Offs:", + xmin, dy, width, 19, + &iuser->offset, 0.0, 10000.0, 0, 0, "Offsets the number of the frame to use in the animation"); + uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Cycl", + xmin+width, dy, width-20, 19, + &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic"); + uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC+node->nr, ICON_AUTO, + xmax-20, dy, 20, 19, + &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes"); + } + if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) { + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + if(rl) { + width= (xmax-xmin); + dy-= 19; + strp= layer_menu(ima->rr); + bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, + xmin, dy, width, 19, + &iuser->layer, 0.0, 10000.0, 0, 0, "Layer"); + uiButSetFunc(bt, image_layer_cb, ima, node->storage); + MEM_freeN(strp); + } + } } } - if(node->storage) - return 57; + if(node->id) { + Image *ima= (Image *)node->id; + int retval= 19; + + /* for each draw we test for anim refresh event */ + if(iuser->flag & IMA_ANIM_REFRESHED) { + iuser->flag &= ~IMA_ANIM_REFRESHED; + addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr); + } + + if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) + retval+= 38; + if( ima->type==IMA_TYPE_MULTILAYER) + retval+= 19; + return retval; + } else return 19; } @@ -1445,27 +1517,27 @@ static void draw_nodespace_grid(SpaceNode *snode) static void draw_nodespace_back(ScrArea *sa, SpaceNode *snode) { - Image *ima; - int x, y; - + draw_nodespace_grid(snode); if(snode->flag & SNODE_BACKDRAW) { - ima= (Image *)find_id("IM", "Viewer Node"); - if(ima && ima->ibuf) { + Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf) { + int x, y; /* somehow the offset has to be calculated inverse */ glaDefine2DArea(&sa->winrct); /* ortho at pixel level curarea */ myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); - x = (sa->winx-ima->ibuf->x)/2 + snode->xof; - y = (sa->winx-ima->ibuf->y)/2 + snode->yof; + x = (sa->winx-ibuf->x)/2 + snode->xof; + y = (sa->winx-ibuf->y)/2 + snode->yof; - if(ima->ibuf->rect) - glaDrawPixelsSafe(x, y, ima->ibuf->x, ima->ibuf->y, ima->ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ima->ibuf->rect); - else - glaDrawPixelsSafe(x, y, ima->ibuf->x, ima->ibuf->y, ima->ibuf->x, GL_RGBA, GL_FLOAT, ima->ibuf->rect_float); + if(ibuf->rect) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + else if(ibuf->channels==4) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); /* sort this out, this should not be needed */ myortho2(snode->v2d.cur.xmin, snode->v2d.cur.xmax, snode->v2d.cur.ymin, snode->v2d.cur.ymax); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index d22408f02e3..4706dcff9d0 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -168,22 +168,6 @@ static void star_stuff_term_func(void) glEnd(); } -static void setalpha_bgpic(BGpic *bgpic) -{ - int x, y, alph; - char *rect; - - alph= (int)(255.0*(1.0-bgpic->blend)); - - rect= (char *)bgpic->rect; - for(y=0; y< bgpic->yim; y++) { - for(x= bgpic->xim; x>0; x--, rect+=4) { - rect[3]= alph; - } - } -} - - void default_gl_light(void) { int a; @@ -349,63 +333,24 @@ static void draw_bgpic(void) { BGpic *bgpic; Image *ima; + ImBuf *ibuf= NULL; float vec[4], fac, asp, zoomx, zoomy; float x1, y1, x2, y2, cx, cy; bgpic= G.vd->bgpic; if(bgpic==NULL) return; - if(bgpic->tex) { - extern void init_render_texture(struct Render *re, Tex *tex); - /* note; bad call, this has to be recoded to move to blenkernel */ - init_render_texture(NULL, bgpic->tex); - free_unused_animimages(); - ima= bgpic->tex->ima; - } - else { - ima= bgpic->ima; - } - - if(ima==NULL) return; - if(ima->ok==0) return; - - tag_image_time(ima); - - /* test for image */ - if(ima->ibuf==NULL) { + ima= bgpic->ima; - if(bgpic->rect) MEM_freeN(bgpic->rect); - bgpic->rect= NULL; - - if(bgpic->tex) { - ima_ibuf_is_nul(bgpic->tex, bgpic->tex->ima); - } - else { - waitcursor(1); - load_image(ima, IB_rect, G.sce, G.scene->r.cfra); - waitcursor(0); - } - if(ima->ibuf==NULL) { - ima->ok= 0; - return; - } - } - - /* this ensures that when ibuf changed (reloaded) the backbuf changes too */ - if(bgpic->ibuf!=ima->ibuf) { - if(bgpic->rect) MEM_freeN(bgpic->rect); - bgpic->rect= NULL; - } - bgpic->ibuf= ima->ibuf; + if(ima) + ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser); + if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) ) + return; + if(ibuf->channels!=4) + return; + if(ibuf->rect==NULL) + IMB_rect_from_float(ibuf); - if(bgpic->rect==NULL) { - - bgpic->rect= MEM_dupallocN(ima->ibuf->rect); - bgpic->xim= ima->ibuf->x; - bgpic->yim= ima->ibuf->y; - setalpha_bgpic(bgpic); - } - if(G.vd->persp==2) { rctf vb; @@ -425,7 +370,7 @@ static void draw_bgpic(void) fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) ); fac= 1.0/fac; - asp= ( (float)ima->ibuf->y)/(float)ima->ibuf->x; + asp= ( (float)ibuf->y)/(float)ibuf->x; vec[0] = vec[1] = vec[2] = 0.0; view3d_project_float(curarea, vec, sco, G.vd->persmat); @@ -445,10 +390,27 @@ static void draw_bgpic(void) if(x1 > curarea->winx ) return; if(y1 > curarea->winy ) return; - zoomx= (x2-x1)/ima->ibuf->x; - zoomy= (y2-y1)/ima->ibuf->y; - - glEnable(GL_BLEND); + zoomx= (x2-x1)/ibuf->x; + zoomy= (y2-y1)/ibuf->y; + + /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ + if(zoomx < 1.0f || zoomy < 1.0f) { + float tzoom= MIN2(zoomx, zoomy); + int mip= 0; + + if(ibuf->mipmap[0]==NULL) + IMB_makemipmap(ibuf, 0); + + while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) { + tzoom*= 2.0f; + zoomx*= 2.0f; + zoomy*= 2.0f; + mip++; + } + if(mip>0) + ibuf= ibuf->mipmap[mip-1]; + } + if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -459,16 +421,18 @@ static void draw_bgpic(void) glPushMatrix(); glaDefine2DArea(&curarea->winrct); + glEnable(GL_BLEND); + glPixelTransferf(GL_ALPHA_SCALE, (1.0f-bgpic->blend)); glPixelZoom(zoomx, zoomy); - glaDrawPixelsSafe(x1, y1, ima->ibuf->x, ima->ibuf->y, ima->ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, bgpic->rect); + glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); glPixelZoom(1.0, 1.0); + glPixelTransferf(GL_ALPHA_SCALE, 1.0f); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); - glBlendFunc(GL_ONE, GL_ZERO); glDisable(GL_BLEND); if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); @@ -1213,9 +1177,6 @@ ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax) dr++; } - ibuf->ftype= PNG; - IMB_saveiff(ibuf, "/tmp/rt.png", IB_rect); - /* put clipped result back, if needed */ if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return ibuf; @@ -1444,7 +1405,6 @@ static void draw_view_icon(void) BIF_icon_draw(5.0, 5.0, icon); - glBlendFunc(GL_ONE, GL_ZERO); glDisable(GL_BLEND); } @@ -1475,54 +1435,6 @@ static void draw_viewport_name(ScrArea *sa) /* ******************* view3d space & buttons ************** */ -static void view3d_change_bgpic_ima(View3D *v3d, Image *newima) { - if (v3d->bgpic && v3d->bgpic->ima!=newima) { - if (newima) - id_us_plus((ID*) newima); - if (v3d->bgpic->ima) - v3d->bgpic->ima->id.us--; - v3d->bgpic->ima= newima; - - if(v3d->bgpic->rect) MEM_freeN(v3d->bgpic->rect); - v3d->bgpic->rect= NULL; - - allqueue(REDRAWVIEW3D, 0); - } -} -static void view3d_change_bgpic_tex(View3D *v3d, Tex *newtex) { - if (v3d->bgpic && v3d->bgpic->tex!=newtex) { - if (newtex) - id_us_plus((ID*) newtex); - if (v3d->bgpic->tex) - v3d->bgpic->tex->id.us--; - v3d->bgpic->tex= newtex; - - allqueue(REDRAWVIEW3D, 0); - } -} - -static void load_bgpic_image(char *name) -{ - Image *ima; - View3D *vd; - - areawinset(curarea->win); - vd= G.vd; - if(vd==0 || vd->bgpic==0) return; - - ima= add_image(name); - if(ima) { - if(vd->bgpic->ima) { - vd->bgpic->ima->id.us--; - } - vd->bgpic->ima= ima; - - free_image_buffers(ima); /* force read again */ - ima->ok= 1; - } - allqueue(REDRAWVIEW3D, 0); - -} /* temporal struct for storing transform properties */ typedef struct { @@ -1975,63 +1887,12 @@ void do_viewbuts(unsigned short event) View3D *vd; Object *ob= OBACT; TransformProperties *tfp= G.vd->properties_storage; - char *name; vd= G.vd; - if(vd==0) return; + if(vd==NULL) return; switch(event) { - case B_LOADBGPIC: - if(vd->bgpic && vd->bgpic->ima) name= vd->bgpic->ima->name; - else name= G.ima; - - if(G.qual==LR_CTRLKEY) - activate_imageselect(FILE_SPECIAL, "Select Image", name, load_bgpic_image); - else - activate_fileselect(FILE_SPECIAL, "Select Image", name, load_bgpic_image); - break; - - case B_BLENDBGPIC: - if(vd->bgpic && vd->bgpic->rect) setalpha_bgpic(vd->bgpic); - addqueue(curarea->win, REDRAW, 1); - break; - - case B_BGPICBROWSE: - if(vd->bgpic) { - if (vd->menunr==-2) { - activate_databrowse((ID*) vd->bgpic->ima, ID_IM, 0, B_BGPICBROWSE, &vd->menunr, do_viewbuts); - } else if (vd->menunr>0) { - Image *newima= (Image*) BLI_findlink(&G.main->image, vd->menunr-1); - - if (newima) - view3d_change_bgpic_ima(vd, newima); - } - } - break; - - case B_BGPICCLEAR: - if (vd->bgpic) - view3d_change_bgpic_ima(vd, NULL); - break; - case B_BGPICTEX: - if (vd->bgpic) { - if (vd->texnr==-2) { - activate_databrowse((ID*) vd->bgpic->tex, ID_TE, 0, B_BGPICTEX, &vd->texnr, do_viewbuts); - } else if (vd->texnr>0) { - Tex *newtex= (Tex*) BLI_findlink(&G.main->tex, vd->texnr-1); - - if (newtex) - view3d_change_bgpic_tex(vd, newtex); - } - } - break; - - case B_BGPICTEXCLEAR: - if (vd->bgpic) - view3d_change_bgpic_tex(vd, NULL); - break; - case B_OBJECTPANEL: DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); allqueue(REDRAWVIEW3D, 1); @@ -2371,8 +2232,6 @@ static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND { uiBlock *block; View3D *vd; - ID *id; - char *strp; vd= G.vd; @@ -2386,68 +2245,29 @@ static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND } if(vd->flag & V3D_DISPBGPIC) { - if(vd->bgpic==0) { + if(vd->bgpic==NULL) { vd->bgpic= MEM_callocN(sizeof(BGpic), "bgpic"); vd->bgpic->size= 5.0; vd->bgpic->blend= 0.5; + vd->bgpic->iuser.fie_ima= 2; + vd->bgpic->iuser.ok= 1; } } - uiDefButBitS(block, TOG, V3D_DISPBGPIC, REDRAWVIEW3D, "Use Background Image", 0, 162, 200, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of the 3D View"); - - uiDefBut(block, LABEL, 1, " ", 206, 162, 84, 20, NULL, 0.0, 0.0, 0, 0, ""); - - - if(vd->flag & V3D_DISPBGPIC) { - - /* Background Image */ - uiDefBut(block, LABEL, 1, "Image:", 0, 128, 76, 19, NULL, 0.0, 0.0, 0, 0, ""); - + if(!(vd->flag & V3D_DISPBGPIC)) { + uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use Background Image", 10, 180, 150, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of the 3D View"); + uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + } + else { uiBlockBeginAlign(block); - uiDefIconBut(block, BUT, B_LOADBGPIC, ICON_FILESEL, 90, 128, 20, 20, 0, 0, 0, 0, 0, "Open a new background image"); + uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use", 10, 225, 50, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of the 3D View"); + uiDefButF(block, NUMSLI, B_REDR, "Blend:", 60, 225, 150, 20, &vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the transparency of the background image"); + uiDefButF(block, NUM, B_REDR, "Size:", 210, 225, 100, 20, &vd->bgpic->size, 0.1, 250.0*vd->grid, 100, 0, "Set the size (width) of the background image"); - id= (ID *)vd->bgpic->ima; - IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(vd->menunr)); - if(strp[0]) { - - uiDefButS(block, MENU, B_BGPICBROWSE, strp, 110, 128, 20, 20, &(vd->menunr), 0, 0, 0, 0, "Select a background image"); + uiDefButF(block, NUM, B_REDR, "X Offset:", 10, 205, 150, 20, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image"); + uiDefButF(block, NUM, B_REDR, "Y Offset:", 160, 205, 150, 20, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image"); - if(vd->bgpic->ima) { - uiDefBut(block, TEX, 0,"BG: ", 130, 128, 140, 20, &vd->bgpic->ima->name,0.0,100.0, 0, 0, "The currently selected background image"); - uiDefIconBut(block, BUT, B_BGPICCLEAR, ICON_X, 270, 128, 20, 20, 0, 0, 0, 0, 0, "Remove background image link"); - } - uiBlockEndAlign(block); - } else { - uiBlockEndAlign(block); - } - MEM_freeN(strp); - - - /* Background texture */ - uiDefBut(block, LABEL, 1, "Texture:", 0, 100, 76, 19, NULL, 0.0, 0.0, 0, 0, ""); - - id= (ID *)vd->bgpic->tex; - IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->tex), id, &(vd->texnr)); - if (strp[0]) - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_BGPICTEX, strp, 90, 100, 20,20, &(vd->texnr), 0, 0, 0, 0, "Select a texture to use as an animated background image"); - MEM_freeN(strp); - - if (id) { - uiDefBut(block, TEX, B_IDNAME, "TE:", 110, 100, 160, 20, id->name+2, 0.0, 18.0, 0, 0, ""); - uiDefIconBut(block, BUT, B_BGPICTEXCLEAR, ICON_X, 270, 100, 20, 20, 0, 0, 0, 0, 0, "Remove background texture link"); - uiBlockEndAlign(block); - } else { - uiBlockEndAlign(block); - } - - uiDefButF(block, NUMSLI, B_BLENDBGPIC, "Blend:", 0, 60 , 290, 19, &vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the transparency of the background image"); - - uiDefButF(block, NUM, REDRAWVIEW3D, "Size:", 0, 28, 140, 19, &vd->bgpic->size, 0.1, 250.0*vd->grid, 100, 0, "Set the size (width) of the background image"); - - uiDefButF(block, NUM, REDRAWVIEW3D, "X Offset:", 0, 6, 140, 19, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Y Offset:", 150, 6, 140, 19, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image"); - + uiblock_image_panel(block, &vd->bgpic->ima, &vd->bgpic->iuser, B_REDR, B_REDR); } } diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 9eb3f8794e4..e2faa3649eb 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -154,7 +154,9 @@ static void snode_handle_recalc(SpaceNode *snode) snode->nodetree->timecursor= set_timecursor; G.afbreek= 0; snode->nodetree->test_break= blender_test_break; - + + BIF_store_spare(); + ntreeCompositExecTree(snode->nodetree, &G.scene->r, 1); /* 1 is do_previews */ snode->nodetree->timecursor= NULL; @@ -191,7 +193,7 @@ static void load_node_image(char *str) /* called from fileselect */ bNode *node= nodeGetActive(snode->edittree); Image *ima= NULL; - ima= add_image(str); + ima= BKE_add_image_file(str); if(ima) { if(node->id) node->id->us--; @@ -201,8 +203,7 @@ static void load_node_image(char *str) /* called from fileselect */ BLI_strncpy(node->name, node->id->name+2, 21); - free_image_buffers(ima); /* force read again */ - ima->ok= 1; + BKE_image_signal(ima, node->storage, IMA_SIGNAL_RELOAD); NodeTagChanged(snode->edittree, node); snode_handle_recalc(snode); @@ -417,6 +418,28 @@ void snode_set_context(SpaceNode *snode) snode->edittree= snode->nodetree; } +/* on activate image viewer, check if we show it */ +static void node_active_image(Image *ima) +{ + ScrArea *sa; + SpaceImage *sima= NULL; + + /* find an imagewindow showing render result */ + for(sa=G.curscreen->areabase.first; sa; sa= sa->next) { + if(sa->spacetype==SPACE_IMAGE) { + sima= sa->spacedata.first; + if(sima->image && sima->image->source!=IMA_SRC_VIEWER) + break; + } + } + if(sa && sima) { + sima->image= ima; + scrarea_queue_winredraw(sa); + scrarea_queue_headredraw(sa); + } +} + + static void node_set_active(SpaceNode *snode, bNode *node) { @@ -460,18 +483,17 @@ static void node_set_active(SpaceNode *snode, bNode *node) snode_handle_recalc(snode); } - /* add node doesnt link this yet... */ - if(node->id==NULL) { - node->id= find_id("IM", "Viewer Node"); - if(node->id==NULL) { - Image *ima= alloc_libblock(&G.main->image, ID_IM, "Viewer Node"); - strcpy(ima->name, "Viewer Node"); - ima->ok= 1; - ima->xrep= ima->yrep= 1; - node->id= &ima->id; - } - else - node->id->us++; + /* addnode() doesnt link this yet... */ + node->id= (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + } + else if(node->type==CMP_NODE_IMAGE) { + if(node->id) + node_active_image((Image *)node->id); + } + else if(node->type==CMP_NODE_R_LAYERS) { + if(node->id==NULL || node->id==(ID *)G.scene) { + G.scene->r.actlay= node->custom1; + allqueue(REDRAWBUTSSCENE, 0); } } } @@ -746,19 +768,21 @@ void snode_zoom_in(ScrArea *sa) static void snode_bg_viewmove(SpaceNode *snode) { ScrArea *sa; + Image *ima; + ImBuf *ibuf; + Window *win; short mval[2], mvalo[2]; short rectx, recty, xmin, xmax, ymin, ymax, pad; - Window *win; int oldcursor; - Image *ima; - ima= (Image *)find_id("IM", "Viewer Node"); + ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ibuf= BKE_image_get_ibuf(ima, NULL); sa = snode->area; - if(ima && ima->ibuf) { - rectx = ima->ibuf->x; - recty = ima->ibuf->y; + if(ibuf) { + rectx = ibuf->x; + recty = ibuf->y; } else { rectx = recty = 1; } @@ -1472,8 +1496,9 @@ bNode *node_add_node(SpaceNode *snode, int type, float locx, float locy) id_us_plus(node->id); if(snode->nodetree->type==NTREE_COMPOSIT) - ntreeCompositForceHidden(G.scene->nodetree); + ntreeCompositForceHidden(snode->edittree); + NodeTagChanged(snode->edittree, node); } return node; } @@ -1884,6 +1909,43 @@ void node_read_renderlayers(SpaceNode *snode) snode_handle_recalc(snode); } +/* gets active viewer user */ +struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) +{ + bNode *node; + + if(ntree) + for(node= ntree->nodes.first; node; node= node->next) + if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) + if(node->flag & NODE_DO_OUTPUT) + return node->storage; + return NULL; +} + +void imagepaint_composite_tags(bNodeTree *ntree, Image *image, ImageUser *iuser) +{ + bNode *node; + + if(ntree==NULL) + return; + + /* search for renderresults */ + if(image->type==IMA_TYPE_R_RESULT) { + for(node= ntree->nodes.first; node; node= node->next) { + if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) { + /* imageuser comes from ImageWin, so indexes are offset 1 */ + if(node->custom1==iuser->layer-1) + NodeTagChanged(ntree, node); + } + } + } + else { + for(node= ntree->nodes.first; node; node= node->next) { + if(node->id== &image->id) + NodeTagChanged(ntree, node); + } + } +} /* ********************** */ @@ -2085,6 +2147,9 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) else node_adduplicate(snode); } break; + case EKEY: + snode_handle_recalc(snode); + break; case GKEY: if(fromlib) fromlib= -1; else { diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 861306a62cb..913a49c28e2 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -107,6 +107,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_ipo.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -5049,8 +5050,9 @@ void image_aspect(void) for(b=0; bmtex[b] && ma->mtex[b]->tex) { tex= ma->mtex[b]->tex; - if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) { - + if(tex->type==TEX_IMAGE && tex->ima) { + ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, NULL); + /* texturespace */ space= 1.0; if(ob->type==OB_MESH) { @@ -5063,8 +5065,8 @@ void image_aspect(void) space= cu->size[0]/cu->size[1]; } - x= tex->ima->ibuf->x/space; - y= tex->ima->ibuf->y; + x= ibuf->x/space; + y= ibuf->y; if(x>y) ob->size[0]= ob->size[1]*x/y; else ob->size[1]= ob->size[0]*y/x; diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index d69b1db1365..a8551656343 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -480,8 +480,7 @@ static void headmenu(ScrArea *sa) static void addqueue_ext(short win, unsigned short event, short val, char ascii) { if (win<4 || !areawinar[win]) { - if(win==0 && !G.background) /* other win ids are for mainwin & renderwin */ - printf("bad call to addqueue: %d (%d, %d)\n", win, event, val); + /* other win ids are for mainwin & renderwin */ } else { BWinEvent evt; @@ -1842,8 +1841,8 @@ static void del_area(ScrArea *sa) if(sa==g_activearea) g_activearea= NULL; } -/* sa2 to sa1 */ -static void copy_areadata(ScrArea *sa1, ScrArea *sa2) +/* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */ +static void copy_areadata(ScrArea *sa1, ScrArea *sa2, int swap_space) { Panel *pa1, *pa2, *patab; ScriptLink *slink1 = &sa1->scriptlink, *slink2 = &sa2->scriptlink; @@ -1852,8 +1851,13 @@ static void copy_areadata(ScrArea *sa1, ScrArea *sa2) sa1->spacetype= sa2->spacetype; Mat4CpyMat4(sa1->winmat, sa2->winmat); - freespacelist(sa1); - duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata); + if(swap_space) { + SWAP(ListBase, sa1->spacedata, sa2->spacedata); + } + else { + freespacelist(sa1); + duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata); + } BLI_freelistN(&sa1->panels); duplicatelist(&sa1->panels, &sa2->panels); @@ -2332,7 +2336,7 @@ void area_fullscreen(void) /* with curarea */ headertype = curarea->headertype; } - copy_areadata(old, curarea); + copy_areadata(old, curarea, 1); /* 1 = swap spacelist */ old->headertype = headertype; old->full= 0; @@ -2364,7 +2368,7 @@ void area_fullscreen(void) /* with curarea */ G.curscreen= oldscreen; /* needed because of setscreen */ /* copy area */ - copy_areadata(newa, curarea); + copy_areadata(newa, curarea, 1); /* 1 = swap spacelist */ curarea->full= oldscreen; newa->full= oldscreen; @@ -2416,7 +2420,7 @@ static void area_autoplayscreen(void) G.curscreen= oldscreen; /* because of setscreen */ /* copy area settings */ - copy_areadata(newa, curarea); + copy_areadata(newa, curarea, 1); /* swap spacedata */ newa->headertype= 0; curarea->full= oldscreen; @@ -2470,7 +2474,7 @@ static void copy_screen(bScreen *to, bScreen *from) sa->spacedata.first= sa->spacedata.last= NULL; sa->uiblocks.first= sa->uiblocks.last= NULL; sa->panels.first= sa->panels.last= NULL; - copy_areadata(sa, saf); + copy_areadata(sa, saf, 0); sa= sa->next; saf= saf->next; @@ -2939,7 +2943,7 @@ static void splitarea(ScrArea *sa, char dir, float fac) /* new areas: top */ newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype); - copy_areadata(newa, sa); + copy_areadata(newa, sa, 0); /* area below */ sa->v2= sv1; @@ -2960,7 +2964,7 @@ static void splitarea(ScrArea *sa, char dir, float fac) /* new areas: left */ newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype); - copy_areadata(newa, sa); + copy_areadata(newa, sa, 0); /* area right */ sa->v1= sv1; diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 3e25340048f..d7b025c53f3 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -49,17 +49,20 @@ #include "BLI_arithb.h" #include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object) #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_screen_types.h" +#include "DNA_texture_types.h" #include "DNA_userdef_types.h" -#include "DNA_space_types.h" -#include "DNA_image_types.h" -#include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object) +#include "DNA_view3d_types.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" @@ -69,6 +72,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_packedFile.h" #include "BKE_utildefines.h" @@ -97,6 +101,8 @@ #include "BMF_Api.h" +#include "RE_pipeline.h" + #include "blendef.h" #include "mydevice.h" @@ -142,10 +148,10 @@ int is_uv_tface_editing_allowed(void) void get_connected_limit_tface_uv(float *limit) { - if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 && - G.sima->image->ibuf->y > 0) { - limit[0]= 0.05/(float)G.sima->image->ibuf->x; - limit[1]= 0.05/(float)G.sima->image->ibuf->y; + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + if(ibuf && ibuf->x > 0 && ibuf->y > 0) { + limit[0]= 0.05/(float)ibuf->x; + limit[1]= 0.05/(float)ibuf->y; } else limit[0]= limit[1]= 0.05/256.0; @@ -154,18 +160,20 @@ void get_connected_limit_tface_uv(float *limit) void clever_numbuts_sima(void) { float ocent[2], cent[2]= {0.0, 0.0}; - int imx, imy; + int imx= 256, imy= 256; int i, nactive= 0; Mesh *me; if( is_uv_tface_editing_allowed()==0 ) return; me= get_mesh(OBACT); - if (G.sima->image && G.sima->image->ibuf) { - imx= G.sima->image->ibuf->x; - imy= G.sima->image->ibuf->y; - } else - imx= imy= 256; + if (G.sima->image) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + if(ibuf) { + imx= ibuf->x; + imy= ibuf->y; + } + } for (i=0; itotface; i++) { MFace *mf= &((MFace*) me->mface)[i]; @@ -312,9 +320,11 @@ void transform_aspect_ratio_tface_uv(float *aspx, float *aspy) void transform_width_height_tface_uv(int *width, int *height) { - if(G.sima->image && G.sima->image->ibuf) { - *width= G.sima->image->ibuf->x; - *height= G.sima->image->ibuf->y; + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + + if(ibuf) { + *width= ibuf->x; + *height= ibuf->y; } else { *width= 256; @@ -861,14 +871,14 @@ void sel_uvco_inside_radius(short sel, MTFace *tface, int index, float *offset, /** gets image dimensions of the 2D view 'v' */ static void getSpaceImageDimension(SpaceImage *sima, float *xy) { - Image *img = sima->image; + ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); float z; z = sima->zoom; - if (img && img->ibuf) { - xy[0] = img->ibuf->x * z; - xy[1] = img->ibuf->y * z; + if (ibuf) { + xy[0] = ibuf->x * z; + xy[1] = ibuf->y * z; } else { xy[0] = 256 * z; xy[1] = 256 * z; @@ -1049,13 +1059,15 @@ void stitch_uv_tface(int mode) return; } - if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 && - G.sima->image->ibuf->y > 0) { - limit[1]= limit[0]/(float)G.sima->image->ibuf->y; - limit[0]= limit[0]/(float)G.sima->image->ibuf->x; + limit[0]= limit[1]= limit[0]/256.0; + if(G.sima->image) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); + + if(ibuf && ibuf->x > 0 && ibuf->y > 0) { + limit[1]= limit[0]/(float)ibuf->y; + limit[0]= limit[0]/(float)ibuf->x; + } } - else - limit[0]= limit[1]= limit[0]/256.0; me= get_mesh(OBACT); tf= me->mtface; @@ -1418,7 +1430,7 @@ int minmax_tface_uv(float *min, float *max) return sel; } -static void sima_show_info(int x, int y, char *cp, float *fp, int *zp, float *zpf) +static void sima_show_info(int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf) { short ofs; char str[256]; @@ -1426,8 +1438,14 @@ static void sima_show_info(int x, int y, char *cp, float *fp, int *zp, float *zp ofs= sprintf(str, "X: %d Y: %d ", x, y); if(cp) ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]); - if(fp) - ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]); + if(fp) { + if(channels==4) + ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]); + else if(channels==1) + ofs+= sprintf(str+ofs, "| Val: %.3f ", fp[0]); + else if(channels==3) + ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f ", fp[0], fp[1], fp[2]); + } if(zp) ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff)); if(zpf) @@ -1449,13 +1467,12 @@ static void sima_show_info(int x, int y, char *cp, float *fp, int *zp, float *zp void sima_sample_color(void) { - ImBuf *ibuf; + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); float fx, fy; short mval[2], mvalo[2], firsttime=1; - if(G.sima->image==NULL) return; - if(G.sima->image->ibuf==NULL) return; - ibuf= G.sima->image->ibuf; + if(ibuf==NULL) + return; calc_image_view(G.sima, 'f'); getmouseco_areawin(mvalo); @@ -1485,7 +1502,7 @@ void sima_sample_color(void) if(ibuf->zbuf_float) zpf= ibuf->zbuf_float + y*ibuf->x + x; if(ibuf->rect_float) - fp= (ibuf->rect_float + 4*(y*ibuf->x + x)); + fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x)); if(G.sima->cumap) { float vec[3]; @@ -1496,20 +1513,22 @@ void sima_sample_color(void) vec[2]= (float)cp[2]/255.0f; } - if(G.qual & LR_CTRLKEY) { - curvemapping_set_black_white(G.sima->cumap, NULL, fp); - curvemapping_do_image(G.sima->cumap, G.sima->image); - } - else if(G.qual & LR_SHIFTKEY) { - curvemapping_set_black_white(G.sima->cumap, fp, NULL); - curvemapping_do_image(G.sima->cumap, G.sima->image); + if(ibuf->channels==4) { + if(G.qual & LR_CTRLKEY) { + curvemapping_set_black_white(G.sima->cumap, NULL, fp); + curvemapping_do_ibuf(G.sima->cumap, ibuf); + } + else if(G.qual & LR_SHIFTKEY) { + curvemapping_set_black_white(G.sima->cumap, fp, NULL); + curvemapping_do_ibuf(G.sima->cumap, ibuf); + } } } scrarea_do_windraw(curarea); myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); glLoadIdentity(); - sima_show_info(x, y, cp, fp, zp, zpf); + sima_show_info(ibuf->channels, x, y, cp, fp, zp, zpf); screen_swapbuffers(); } @@ -1524,20 +1543,19 @@ void sima_sample_color(void) static void load_image_filesel(char *str) /* called from fileselect */ { - Image *ima=0; + Image *ima= NULL; if(G.obedit) { error("Can't perfom this in editmode"); return; } - ima= add_image(str); + ima= BKE_add_image_file(str); if(ima) { G.sima->image= ima; - free_image_buffers(ima); /* force read again */ - ima->ok= 1; + BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD); image_changed(G.sima, 0); } @@ -1591,7 +1609,7 @@ static void replace_image_filesel(char *str) /* called from fileselect */ return; } - ima= add_image(str); + ima= BKE_add_image_file(str); if(ima) { if(G.sima->image && G.sima->image != ima) { @@ -1600,8 +1618,8 @@ static void replace_image_filesel(char *str) /* called from fileselect */ G.sima->image= ima; - free_image_buffers(ima); /* force read again */ - ima->ok= 1; + BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD); + /* replace also assigns: */ image_changed(G.sima, 0); @@ -1610,42 +1628,69 @@ static void replace_image_filesel(char *str) /* called from fileselect */ allqueue(REDRAWIMAGE, 0); } -static void save_image_filesel(char *name) + +static void save_image_doit(char *name) { - Image *ima = G.sima->image; + Image *ima= G.sima->image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); int len; char str[FILE_MAXDIR+FILE_MAXFILE]; - if (ima && ima->ibuf) { + if (ibuf) { BLI_strncpy(str, name, sizeof(str)); BLI_convertstringcode(str, G.sce, G.scene->r.cfra); if(G.scene->r.scemode & R_EXTENSION) - BKE_add_image_extension(str, G.scene->r.imtype); - + BKE_add_image_extension(str, G.sima->imtypenr); + if (saveover(str)) { + /* enforce user setting for RGB or RGBA, but skip BW */ if(G.scene->r.planes==32) - ima->ibuf->depth= 32; + ibuf->depth= 32; else if(G.scene->r.planes==24) - ima->ibuf->depth= 24; + ibuf->depth= 24; waitcursor(1); - if (BKE_write_ibuf(ima->ibuf, str, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality)) { + if(G.sima->imtypenr==R_MULTILAYER) { + RenderResult *rr= BKE_image_get_renderresult(ima); + if(rr) { + RE_WriteRenderResult(rr, str); + + BLI_strncpy(ima->name, name, sizeof(ima->name)); + BLI_strncpy(ibuf->name, str, sizeof(ibuf->name)); + + /* should be function? nevertheless, saving only happens here */ + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) + ibuf->userflags &= ~IB_BITMAPDIRTY; + + } + else error("Did not write, no Multilayer Image"); + } + else if (BKE_write_ibuf(ibuf, str, G.sima->imtypenr, G.scene->r.subimtype, G.scene->r.quality)) { BLI_strncpy(ima->name, name, sizeof(ima->name)); - BLI_strncpy(ima->ibuf->name, str, sizeof(ima->ibuf->name)); - ima->ibuf->userflags &= ~IB_BITMAPDIRTY; - allqueue(REDRAWHEADERS, 0); - allqueue(REDRAWBUTSSHADING, 0); - } else { + BLI_strncpy(ibuf->name, str, sizeof(ibuf->name)); + + ibuf->userflags &= ~IB_BITMAPDIRTY; + + /* change type? */ + if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) + ima->source= IMA_SRC_FILE; + if(ima->type==IMA_TYPE_R_RESULT) + ima->type= IMA_TYPE_IMAGE; + + /* name image as how we saved it */ + len= strlen(str); + while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--; + rename_id(&ima->id, str+len); + } + else { error("Couldn't write image: %s", str); } - - /* name image as how we saved it */ - len= strlen(str); - while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--; - rename_id(&ima->id, str+len); + + allqueue(REDRAWHEADERS, 0); + allqueue(REDRAWBUTSSHADING, 0); waitcursor(0); } @@ -1682,64 +1727,138 @@ void replace_image_sima(short imageselect) activate_fileselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel); } -void save_as_image_sima() + +static char *filesel_imagetype_string(Image *ima) +{ + char *strp, *str= MEM_callocN(14*32, "menu for filesel"); + + strp= str; + str += sprintf(str, "Save Image as: %%t|"); + str += sprintf(str, "Targa %%x%d|", R_TARGA); + str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA); + str += sprintf(str, "PNG %%x%d|", R_PNG); + str += sprintf(str, "BMP %%x%d|", R_BMP); + str += sprintf(str, "Jpeg %%x%d|", R_JPEG90); + str += sprintf(str, "Iris %%x%d|", R_IRIS); + if(G.have_libtiff) + str += sprintf(str, "Tiff %%x%d|", R_TIFF); + str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR); + str += sprintf(str, "Cineon %%x%d|", R_CINEON); + str += sprintf(str, "DPX %%x%d|", R_DPX); +#ifdef WITH_OPENEXR + str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR); + /* saving sequences of multilayer won't work, they copy buffers */ + if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER); + else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER); +#endif + return strp; +} + +/* always opens fileselect */ +void save_as_image_sima(void) { Image *ima = G.sima->image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); char name[FILE_MAXDIR+FILE_MAXFILE]; if (ima) { strcpy(name, ima->name); - if (ima->ibuf) { - char str[64]; - save_image_filesel_str(str); + if (ibuf) { + char *strp; - /* so it shows an extension in filewindow */ - if(G.scene->r.scemode & R_EXTENSION) - BKE_add_image_extension(name, G.scene->r.imtype); + strp= filesel_imagetype_string(ima); - activate_fileselect(FILE_SPECIAL, str, name, save_image_filesel); + /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */ + if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER)) + G.sima->imtypenr= R_MULTILAYER; + else if(ima->type==IMA_TYPE_R_RESULT) + G.sima->imtypenr= R_MULTILAYER; + else G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype); + + activate_fileselect_menu(FILE_SPECIAL, "Save Image", name, strp, &G.sima->imtypenr, save_image_doit); } } } -void save_image_sima() +/* if exists, saves over without fileselect */ +void save_image_sima(void) { Image *ima = G.sima->image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); char name[FILE_MAXDIR+FILE_MAXFILE]; if (ima) { strcpy(name, ima->name); - if (ima->ibuf) { - if (BLI_exists(ima->ibuf->name)) - save_image_filesel(ima->ibuf->name); + if (ibuf) { + if (BLI_exists(ibuf->name)) { + if(BKE_image_get_renderresult(ima)) + G.sima->imtypenr= R_MULTILAYER; + else + G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype); + + save_image_doit(ibuf->name); + } else save_as_image_sima(); } } } -void reload_image_sima() +void save_image_sequence_sima(void) { - Image *ima = G.sima->image; - - if (ima && ima->ibuf && BLI_exists(ima->ibuf->name)) { - if (ima->packedfile) { - PackedFile *pf; - pf = newPackedFile(ima->name); - if (pf) { - freePackedFile(ima->packedfile); - ima->packedfile = pf; + ImBuf *ibuf; + int tot= 0; + char di[FILE_MAX], fi[FILE_MAX]; + + if(G.sima->image==NULL) + return; + if(G.sima->image->source!=IMA_SRC_SEQUENCE) + return; + if(G.sima->image->type==IMA_TYPE_MULTILAYER) { + error("Cannot save Multilayer Sequences"); + return; + } + + /* get total */ + for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) + if(ibuf->userflags & IB_BITMAPDIRTY) + tot++; + + if(tot==0) { + notice("No Images have been changed"); + return; + } + /* get a filename for menu */ + for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) + if(ibuf->userflags & IB_BITMAPDIRTY) + break; + + BLI_strncpy(di, ibuf->name, FILE_MAX); + BLI_splitdirstring(di, fi); + + sprintf(fi, "%d Image(s) will be saved in %s", tot, di); + if(okee(fi)) { + + for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) { + if(ibuf->userflags & IB_BITMAPDIRTY) { + if(0 == IMB_saveiff(ibuf, ibuf->name, IB_rect | IB_zbuf | IB_zbuffloat)) { + error("Could not write image", ibuf->name); + break; + } + printf("Saved: %s\n", ibuf->name); + ibuf->userflags &= ~IB_BITMAPDIRTY; } - else - error("Image not available. Keeping packed image."); - } - if (ima->preview) { - free_image_preview(ima); } - free_image_buffers(ima); /* force read again */ - ima->ok= 1; + } +} + +void reload_image_sima(void) +{ + + if (G.sima ) { + BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD); image_changed(G.sima, 0); } @@ -1748,13 +1867,13 @@ void reload_image_sima() BIF_preview_changed(ID_TE); } -void new_image_sima() +void new_image_sima(void) { static int width= 256, height= 256; static short uvtestgrid=0; char name[256]; - strcpy(name, "Image"); + strcpy(name, "Untitled"); add_numbut(0, TEX, "Name:", 0, 255, name, NULL); add_numbut(1, NUM|INT, "Width:", 1, 5000, &width, NULL); @@ -1763,7 +1882,7 @@ void new_image_sima() if (!do_clever_numbuts("New Image", 4, REDRAW)) return; - G.sima->image= new_image(width, height, name, uvtestgrid); + G.sima->image= BKE_add_image_size(width, height, name, uvtestgrid); image_changed(G.sima, 0); BIF_undo_push("Add image"); @@ -1777,28 +1896,80 @@ void pack_image_sima() Image *ima = G.sima->image; if (ima) { - if (ima->packedfile) { - if (G.fileflags & G_AUTOPACK) - if (okee("Disable AutoPack?")) - G.fileflags &= ~G_AUTOPACK; - - if ((G.fileflags & G_AUTOPACK) == 0) { - unpackImage(ima, PF_ASK); - BIF_undo_push("Unpack image"); - } - } - else { - if (ima->ibuf && (ima->ibuf->userflags & IB_BITMAPDIRTY)) { - error("Can't pack painted image. Save the painted image first."); + if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) { + if (ima->packedfile) { + if (G.fileflags & G_AUTOPACK) + if (okee("Disable AutoPack?")) + G.fileflags &= ~G_AUTOPACK; + + if ((G.fileflags & G_AUTOPACK) == 0) { + unpackImage(ima, PF_ASK); + BIF_undo_push("Unpack image"); + } } else { - ima->packedfile = newPackedFile(ima->name); - BIF_undo_push("Pack image"); + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + error("Can't pack painted image. Save image or use Repack as PNG."); + } + else { + ima->packedfile = newPackedFile(ima->name); + BIF_undo_push("Pack image"); + } } + + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWHEADERS, 0); } + } +} + + - allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWHEADERS, 0); +/* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */ +void BIF_image_update_frame(void) +{ + Tex *tex; + + /* texture users */ + for(tex= G.main->tex.first; tex; tex= tex->id.next) { + if(tex->type==TEX_IMAGE && tex->ima) + if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) + if(tex->iuser.flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_imanr(&tex->iuser, G.scene->r.cfra, 0); + + } + /* image window, compo node users */ + if(G.curscreen) { + ScrArea *sa; + for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { + if(sa->spacetype==SPACE_VIEW3D) { + View3D *v3d= sa->spacedata.first; + if(v3d->bgpic) + if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_imanr(&v3d->bgpic->iuser, G.scene->r.cfra, 0); + } + else if(sa->spacetype==SPACE_IMAGE) { + SpaceImage *sima= sa->spacedata.first; + if(sima->iuser.flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_imanr(&sima->iuser, G.scene->r.cfra, 0); + } + else if(sa->spacetype==SPACE_NODE) { + SpaceNode *snode= sa->spacedata.first; + if(snode->treetype==NTREE_COMPOSIT) { + bNode *node; + for(node= snode->nodetree->nodes.first; node; node= node->next) { + if(node->id && node->type==CMP_NODE_IMAGE) { + Image *ima= (Image *)node->id; + ImageUser *iuser= node->storage; + if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) + if(iuser->flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0); + } + } + } + } + } } } diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 0a000d65419..990bcd72ecf 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -718,6 +718,9 @@ static void timeline_force_draw(short val) else if(sa->spacetype==SPACE_BUTS) { if(val & TIME_ALL_BUTS_WIN) dodraw= 1; } + else if(sa->spacetype==SPACE_IMAGE) { + if (val & TIME_ALL_IMAGE_WIN) dodraw = 1; + } else if(sa->spacetype==SPACE_SEQ) { if (val & TIME_SEQ) dodraw = 1; } diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index bcee676ae90..19c35580ff0 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -164,7 +164,7 @@ static rcti scrollrct, textrct, bar; static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0; static int filetoname= 0; static float pixels_to_ofs; -static char otherdir[FILE_MAXDIR+FILE_MAXFILE]; +static char otherdir[FILE_MAX]; static ScrArea *otherarea; /* FSMENU HANDLING */ @@ -441,13 +441,13 @@ static int compare_extension(const void *a1, const void *a2) { } /* **************************************** */ - -void clear_global_filesel_vars() +static int filesel_has_func(SpaceFile *sfile) { - selecting= 0; + if(sfile->returnfunc || sfile->returnfunc_event || sfile->returnfunc_args) + return 1; + return 0; } - void filesel_statistics(SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen) { double len; @@ -497,7 +497,7 @@ void test_flags_file(SpaceFile *sfile) file->flags |= BLENDERFILE; if(sfile->type==FILE_LOADLIB) { - char name[FILE_MAXDIR+FILE_MAXFILE]; + char name[FILE_MAX]; BLI_strncpy(name, sfile->dir, sizeof(name)); strcat(name, file->relname); @@ -614,7 +614,7 @@ void sort_filelist(SpaceFile *sfile) void read_dir(SpaceFile *sfile) { int num, len; - char wdir[FILE_MAXDIR+FILE_MAXFILE]; + char wdir[FILE_MAX]; /* sfile->act is used for example in databrowse: double names of library objects */ sfile->act= -1; @@ -675,7 +675,7 @@ void freefilelist(SpaceFile *sfile) static void split_sfile(SpaceFile *sfile, char *s1) { - char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR+FILE_MAXFILE], file[FILE_MAXDIR+FILE_MAXFILE]; + char string[FILE_MAX], dir[FILE_MAX], file[FILE_MAX]; BLI_strncpy(string, s1, sizeof(string)); @@ -699,7 +699,7 @@ void parent(SpaceFile *sfile) char *dir; /* if databrowse: no parent */ - if(sfile->type==FILE_MAIN && sfile->returnfunc) return; + if(sfile->type==FILE_MAIN && filesel_has_func(sfile)) return; dir= sfile->dir; @@ -1135,7 +1135,7 @@ static char *library_string(void) int nr=0, tot= BLI_countlist(&G.main->library); if(tot==0) return NULL; - str= MEM_callocN(tot*(FILE_MAXDIR+FILE_MAXFILE), "filesel lib menu"); + str= MEM_callocN(tot*(FILE_MAX), "filesel lib menu"); for(tot=0, lib= G.main->library.first; lib; lib= lib->id.next, nr++) { tot+= sprintf(str+tot, "%s %%x%d|", lib->name+2, nr); @@ -1181,7 +1181,8 @@ void drawfilespace(ScrArea *sa, void *spacedata) sprintf(name, "win %d", sa->win); block= uiNewBlock(&sa->uiblocks, name, UI_EMBOSS, UI_HELV, sa->win); - uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL); + /* browse 1 datablock */ + uiSetButLock( sfile->type==FILE_MAIN && filesel_has_func(sfile), NULL); /* space available for load/save buttons? */ loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title)); @@ -1300,10 +1301,15 @@ static void do_filescrollwheel(SpaceFile *sfile, int move) } } -void activate_fileselect(int type, char *title, char *file, void (*func)(char *)) +/* the complete call; pulldown menu, and three callback types */ +static void activate_fileselect_(int type, char *title, char *file, short *menup, char *pupmenu, + void (*func)(char *), + void (*func_event)(unsigned short), + void (*func_args)(char *, void *arg1, void *arg2), + void *arg1, void *arg2) { SpaceFile *sfile; - char group[24], name[FILE_MAXDIR+FILE_MAXFILE], temp[FILE_MAXDIR+FILE_MAXFILE]; + char group[24], name[FILE_MAX], temp[FILE_MAX]; if(curarea==0) return; if(curarea->win==0) return; @@ -1318,10 +1324,21 @@ void activate_fileselect(int type, char *title, char *file, void (*func)(char *) BLI_strncpy(name, file, sizeof(name)); sfile= curarea->spacedata.first; - /* sfile wants a (*)(short), but get (*)(char*) */ + sfile->returnfunc= func; + sfile->returnfunc_event= func_event; + sfile->returnfunc_args= func_args; + sfile->arg1= arg1; + sfile->arg2= arg2; + sfile->type= type; sfile->ofs= 0; + + if(sfile->pupmenu) + MEM_freeN(sfile->pupmenu); + sfile->pupmenu= pupmenu; + sfile->menup= menup; + /* sfile->act is used for databrowse: double names of library objects */ sfile->act= -1; @@ -1372,12 +1389,28 @@ void activate_fileselect(int type, char *title, char *file, void (*func)(char *) filetoname= 1; } +void activate_fileselect(int type, char *title, char *file, void (*func)(char *)) +{ + activate_fileselect_(type, title, file, NULL, NULL, func, NULL, NULL, NULL, NULL); +} + +void activate_fileselect_menu(int type, char *title, char *file, char *pupmenu, short *menup, void (*func)(char *)) +{ + activate_fileselect_(type, title, file, menup, pupmenu, func, NULL, NULL, NULL, NULL); +} + +void activate_fileselect_args(int type, char *title, char *file, void (*func)(char *, void *, void *), void *arg1, void *arg2) +{ + activate_fileselect_(type, title, file, NULL, NULL, NULL, NULL, func, arg1, arg2); +} + + void activate_imageselect(int type, char *title, char *file, void (*func)(char *)) { SpaceImaSel *simasel; - char dir[FILE_MAXDIR+FILE_MAXFILE], name[FILE_MAXDIR+FILE_MAXFILE]; + char dir[FILE_MAX], name[FILE_MAX]; - if(curarea==0) return; + if(curarea==NULL) return; if(curarea->win==0) return; newspace(curarea, SPACE_IMASEL); @@ -1420,19 +1453,47 @@ void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *me if(id) BLI_strncpy(str, id->name, sizeof(str)); else return; - activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func); + activate_fileselect_(FILE_MAIN, "SELECT DATABLOCK", str, menup, NULL, NULL, func, NULL, NULL, NULL); sfile= curarea->spacedata.first; sfile->retval= retval; sfile->ipotype= fromcode; - sfile->menup= menup; } -void filesel_prevspace() +void activate_databrowse_args(struct ID *id, int idcode, int fromcode, short *menup, void (*func)(char *, void *, void *), void *arg1, void *arg2) { + ListBase *lb; SpaceFile *sfile; + char str[32]; + + if(id==NULL) { + lb= wich_libbase(G.main, idcode); + id= lb->first; + } + + if(id) BLI_strncpy(str, id->name, sizeof(str)); + else return; + + activate_fileselect_(FILE_MAIN, "SELECT DATABLOCK", str, menup, NULL, NULL, NULL, func, arg1, arg2); sfile= curarea->spacedata.first; + sfile->ipotype= fromcode; +} + +void filesel_prevspace() +{ + SpaceFile *sfile= curarea->spacedata.first; + + /* cleanup */ + if(sfile->spacetype==SPACE_FILE) { + if(sfile->menup) + sfile->menup= NULL; + if(sfile->pupmenu) { + MEM_freeN(sfile->pupmenu); + sfile->pupmenu= NULL; + } + } + if(sfile->next) { BLI_remlink(&curarea->spacedata, sfile); @@ -1527,11 +1588,11 @@ void free_filesel_spec(char *dir) } } - +/* NOTE: this is called for file read, after the execfunc no UI memory is valid! */ static void filesel_execute(SpaceFile *sfile) { struct direntry *files; - char name[FILE_MAXDIR+FILE_MAXFILE]; + char name[FILE_MAX]; int a; filesel_prevspace(); @@ -1548,7 +1609,7 @@ static void filesel_execute(SpaceFile *sfile) BIF_undo_push("Append from file"); allqueue(REDRAWALL, 1); } - else if(sfile->returnfunc) { + else if(filesel_has_func(sfile)) { fsmenu_insert_entry(sfile->dir, 1); if(sfile->type==FILE_MAIN) { /* DATABROWSE */ @@ -1593,7 +1654,10 @@ static void filesel_execute(SpaceFile *sfile) } } } - sfile->returnfunc((char*) (long)sfile->retval); + if(sfile->returnfunc_event) + sfile->returnfunc_event(sfile->retval); + else if(sfile->returnfunc_args) + sfile->returnfunc_args(NULL, sfile->arg1, sfile->arg2); } else { if(strncmp(sfile->title, "Save", 4)==0) free_filesel_spec(sfile->dir); @@ -1604,22 +1668,27 @@ static void filesel_execute(SpaceFile *sfile) if(sfile->flag & FILE_STRINGCODE) { if (!G.relbase_valid) { - okee("You have to save the .blend file before using relative paths! Using absolute path instead."); - sfile->flag &= ~FILE_STRINGCODE; + /* skip save */ + if(strncmp(sfile->title, "Save", 4)) { + okee("You have to save the .blend file before using relative paths! Using absolute path instead."); + sfile->flag &= ~FILE_STRINGCODE; + } } else { BLI_makestringcode(G.sce, name); } } - - sfile->returnfunc(name); + if(sfile->returnfunc) + sfile->returnfunc(name); + else if(sfile->returnfunc_args) + sfile->returnfunc_args(name, sfile->arg1, sfile->arg2); } } } static void do_filesel_buttons(short event, SpaceFile *sfile) { - char butname[FILE_MAXDIR+FILE_MAXFILE]; + char butname[FILE_MAX]; if (event == B_FS_FILENAME) { if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) { @@ -1864,7 +1933,7 @@ static void fs_fake_users(SpaceFile *sfile) int a; /* only for F4 DATABROWSE */ - if(sfile->returnfunc) return; + if(filesel_has_func(sfile)) return; for(a=0; atotfile; a++) { if(sfile->filelist[a].flags & ACTIVE) { @@ -1907,7 +1976,7 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) SpaceFile *sfile; int act, do_draw= 0, i, test, ret = 0; short qual, mval[2]; - char str[FILE_MAXDIR+FILE_MAXFILE+12]; + char str[FILE_MAX+12]; sfile= curarea->spacedata.first; if(sfile==0) return; @@ -2297,7 +2366,7 @@ static int is_a_library(SpaceFile *sfile, char *dir, char *group) static void do_library_append(SpaceFile *sfile) { Library *lib; - char dir[FILE_MAXDIR+FILE_MAXFILE], group[32]; + char dir[FILE_MAX], group[32]; if ( is_a_library(sfile, dir, group)==0 ) { error("Not a library"); @@ -2344,8 +2413,8 @@ static void library_to_filelist(SpaceFile *sfile) { LinkNode *l, *names; int ok, i, nnames, idcode; - char filename[FILE_MAXDIR+FILE_MAXFILE]; - char dir[FILE_MAXDIR+FILE_MAXFILE], group[24]; + char filename[FILE_MAX]; + char dir[FILE_MAX], group[24]; /* name test */ ok= is_a_library(sfile, dir, group); @@ -2420,7 +2489,7 @@ static void filesel_select_objects(SpaceFile *sfile) int a; /* only when F4 DATABROWSE */ - if(sfile->returnfunc) return; + if(filesel_has_func(sfile)) return; if( strcmp(sfile->dir, "Object/")==0 ) { for(a=0; atotfile; a++) { @@ -2462,7 +2531,7 @@ static void active_file_object(SpaceFile *sfile) Object *ob; /* only when F4 DATABROWSE */ - if(sfile->returnfunc) return; + if(filesel_has_func(sfile)) return; if( strcmp(sfile->dir, "Object/")==0 ) { if(sfile->act >= 0) { @@ -2551,7 +2620,7 @@ void main_to_filelist(SpaceFile *sfile) id= lb->first; sfile->totfile= 0; while(id) { - if(sfile->returnfunc && idcode==ID_IP) { + if(filesel_has_func(sfile) && idcode==ID_IP) { if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++; } else if (hide==0 || id->name[2] != '.') @@ -2560,12 +2629,12 @@ void main_to_filelist(SpaceFile *sfile) id= id->next; } - if(sfile->returnfunc==0) sfile->totfile+= 2; + if(!filesel_has_func(sfile)) sfile->totfile+= 2; sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry)); files= sfile->filelist; - if(sfile->returnfunc==0) { + if(!filesel_has_func(sfile)) { memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry)); sfile->filelist[0].relname= BLI_strdup("."); sfile->filelist[0].type |= S_IFDIR; @@ -2582,7 +2651,7 @@ void main_to_filelist(SpaceFile *sfile) while(id) { ok= 0; - if(sfile->returnfunc && idcode==ID_IP) { + if(filesel_has_func(sfile) && idcode==ID_IP) { if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1; } else ok= 1; @@ -2594,14 +2663,14 @@ void main_to_filelist(SpaceFile *sfile) if(id->lib==NULL) files->relname= BLI_strdup(id->name+2); else { - char tmp[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE]; - BLI_strncpy(tmp, id->lib->name, FILE_MAXDIR+FILE_MAXFILE); + char tmp[FILE_MAX], fi[FILE_MAXFILE]; + BLI_strncpy(tmp, id->lib->name, FILE_MAX); BLI_splitdirstring(tmp, fi); files->relname= MEM_mallocN(FILE_MAXFILE+32, "filename for lib"); sprintf(files->relname, "%s / %s", fi, id->name+2); } - if(sfile->returnfunc==0) { /* F4 DATA BROWSE */ + if(!filesel_has_func(sfile)) { /* F4 DATA BROWSE */ if(idcode==ID_OB) { if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE; } @@ -2646,7 +2715,7 @@ void main_to_filelist(SpaceFile *sfile) if( strcmp(sfile->file, sfile->filelist[a].relname)==0) { sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY)); filetoname= 0; - if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE; + if(filesel_has_func(sfile)) sfile->filelist[a].flags |= ACTIVE; } } } @@ -2656,9 +2725,9 @@ void main_to_filelist(SpaceFile *sfile) void clever_numbuts_filesel() { SpaceFile *sfile; - char orgname[FILE_MAXDIR+FILE_MAXFILE+12]; - char filename[FILE_MAXDIR+FILE_MAXFILE+12]; - char newname[FILE_MAXDIR+FILE_MAXFILE+12]; + char orgname[FILE_MAX+12]; + char filename[FILE_MAX+12]; + char newname[FILE_MAX+12]; int test; int len; diff --git a/source/blender/src/header_filesel.c b/source/blender/src/header_filesel.c index 4e7c94e7181..189cf8dab17 100644 --- a/source/blender/src/header_filesel.c +++ b/source/blender/src/header_filesel.c @@ -127,6 +127,10 @@ void file_buttons(void) xcotitle= xco; xco+= BIF_GetStringWidth(G.font, sfile->title, (U.transopts & USER_TR_BUTTONS)); + if(sfile->pupmenu && sfile->menup) { + uiDefButS(block, MENU, B_NOP, sfile->pupmenu, xco+10,0,90,20, sfile->menup, 0, 0, 0, 0, ""); + xco+= 100; + } uiBlockBeginAlign(block); uiDefIconButBitS(block, ICONTOG, FILE_SHOWSHORT, B_SORTFILELIST, ICON_LONGDISPLAY,xco+=XIC,0,XIC,YIC, &sfile->flag, 0, 0, 0, 0, "Toggles long info"); uiDefIconButBitS(block, TOG, FILE_HIDE_DOT, B_RELOADDIR, ICON_GHOST,xco+=XIC,0,XIC,YIC, &sfile->flag, 0, 0, 0, 0, "Hides dot files"); diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index 5e162b9a22e..d1bfcdbe125 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -42,21 +42,28 @@ #include #endif +#include "DNA_brush_types.h" #include "DNA_ID.h" #include "DNA_image_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_texture_types.h" #include "DNA_userdef_types.h" +#include "BLI_blenlib.h" + #include "BDR_drawmesh.h" #include "BDR_unwrapper.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_main.h" +#include "BKE_utildefines.h" +#include "BIF_butspace.h" #include "BIF_drawimage.h" #include "BIF_editsima.h" #include "BIF_interface.h" @@ -64,26 +71,38 @@ #include "BIF_screen.h" #include "BIF_space.h" #include "BIF_transform.h" +#include "BIF_toolbox.h" +#include "BSE_drawview.h" #include "BSE_filesel.h" #include "BSE_headerbuttons.h" +#include "BSE_trans_types.h" #include "BPY_extern.h" #include "BPY_menus.h" #include "IMB_imbuf_types.h" -#include "BSE_trans_types.h" + +#include "RE_pipeline.h" #include "blendef.h" +#include "butspace.h" #include "mydevice.h" void do_image_buttons(unsigned short event) { + ToolSettings *settings= G.scene->toolsettings; ID *id, *idtest; int nr; if(curarea->win==0) return; + if(event<=100) { + if(event<=50) do_global_buttons2(event); + else do_global_buttons(event); + return; + } + switch(event) { case B_SIMAGEHOME: image_home(); @@ -100,21 +119,15 @@ void do_image_buttons(unsigned short event) nr= 1; id= (ID *)G.sima->image; - idtest= G.main->image.first; - while(idtest) { - if(nr==G.sima->imanr) { - break; - } - nr++; - idtest= idtest->next; - } - if(idtest==0) { /* no new */ + idtest= BLI_findlink(&G.main->image, G.sima->imanr-1); + if(idtest==NULL) { /* no new */ return; } if(idtest!=id) { G.sima->image= (Image *)idtest; if(idtest->us==0) idtest->us= 1; + BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); allqueue(REDRAWIMAGE, 0); } /* also when image is the same: assign! 0==no tileflag: */ @@ -128,10 +141,15 @@ void do_image_buttons(unsigned short event) make_repbind(G.sima->image); image_changed(G.sima, 1); } + /* XXX might be another event needed for this? */ + if(G.sima->image) + if(ELEM(G.sima->image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) + if(G.sima->iuser.flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_imanr(&G.sima->iuser, G.scene->r.cfra, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); break; - + case B_SIMAGEDRAW1: image_changed(G.sima, 2); /* 2: only tileflag */ allqueue(REDRAWVIEW3D, 0); @@ -150,6 +168,11 @@ void do_image_buttons(unsigned short event) pack_image_sima(); break; + case B_SIMA_REPACK: + BKE_image_memorypack(G.sima->image); + allqueue(REDRAWIMAGE, 0); + break; + case B_SIMA_USE_ALPHA: G.sima->flag &= ~(SI_SHOW_ALPHA|SI_SHOW_ZBUF); scrarea_queue_winredraw(curarea); @@ -165,6 +188,157 @@ void do_image_buttons(unsigned short event) scrarea_queue_winredraw(curarea); scrarea_queue_headredraw(curarea); break; + case B_SIMARELOAD: + reload_image_sima(); + break; + case B_SIMAGELOAD: + open_image_sima(0); + break; + case B_SIMANAME: + if(G.sima->image) { + Image *ima; + char str[FILE_MAXDIR+FILE_MAXFILE]; + + /* name in ima has been changed by button! */ + BLI_strncpy(str, G.sima->image->name, sizeof(str)); + ima= BKE_add_image_file(str); + if(ima) { + + G.sima->image= ima; + + BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD); + image_changed(G.sima, 0); + + } + BIF_undo_push("Load image"); + allqueue(REDRAWIMAGE, 0); + } + break; + case B_SIMAMULTI: + if(G.sima && G.sima->image) { + BKE_image_multilayer_index(G.sima->image->rr, &G.sima->iuser); + allqueue(REDRAWIMAGE, 0); + } + break; + case B_TRANS_IMAGE: + image_editvertex_buts(NULL); + break; + + case B_TWINANIM: + { + Image *ima; + int nr; + + ima = G.sima->image; + if (ima) { + if(ima->flag & IMA_TWINANIM) { + nr= ima->xrep*ima->yrep; + if(ima->twsta>=nr) ima->twsta= 1; + if(ima->twend>=nr) ima->twend= nr-1; + if(ima->twsta>ima->twend) ima->twsta= 1; + allqueue(REDRAWIMAGE, 0); + } + } + break; + } + case B_SIMACLONEBROWSE: + if (settings->imapaint.brush) + if (brush_clone_image_set_nr(settings->imapaint.brush, G.sima->menunr)) + allqueue(REDRAWIMAGE, 0); + break; + + case B_SIMACLONEDELETE: + if (settings->imapaint.brush) + if (brush_clone_image_delete(settings->imapaint.brush)) + allqueue(REDRAWIMAGE, 0); + break; + + case B_SIMABRUSHCHANGE: + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWBUTSEDIT, 0); + break; + + case B_SIMACURVES: + curvemapping_do_ibuf(G.sima->cumap, BKE_image_get_ibuf(G.sima->image, &G.sima->iuser)); + allqueue(REDRAWIMAGE, 0); + break; + + case B_SIMARANGE: + curvemapping_set_black_white(G.sima->cumap, NULL, NULL); + curvemapping_do_ibuf(G.sima->cumap, BKE_image_get_ibuf(G.sima->image, &G.sima->iuser)); + allqueue(REDRAWIMAGE, 0); + break; + + case B_SIMABRUSHBROWSE: + if(G.sima->menunr==-2) { + activate_databrowse((ID*)settings->imapaint.brush, ID_BR, 0, B_SIMABRUSHBROWSE, &G.sima->menunr, do_global_buttons); + break; + } + else if(G.sima->menunr < 0) break; + + if(brush_set_nr(&settings->imapaint.brush, G.sima->menunr)) { + BIF_undo_push("Browse Brush"); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWIMAGE, 0); + } + break; + case B_SIMABRUSHDELETE: + if(brush_delete(&settings->imapaint.brush)) { + BIF_undo_push("Unlink Brush"); + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWBUTSEDIT, 0); + } + break; + case B_KEEPDATA: + brush_toggle_fake_user(settings->imapaint.brush); + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWBUTSEDIT, 0); + break; + case B_SIMABRUSHLOCAL: + if(settings->imapaint.brush && settings->imapaint.brush->id.lib) { + if(okee("Make local")) { + make_local_brush(settings->imapaint.brush); + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWBUTSEDIT, 0); + } + } + break; + case B_SIMABTEXBROWSE: + if(settings->imapaint.brush) { + Brush *brush= settings->imapaint.brush; + + if(G.sima->menunr==-2) { + MTex *mtex= brush->mtex[brush->texact]; + ID *id= (ID*)((mtex)? mtex->tex: NULL); + activate_databrowse(id, ID_TE, 0, B_SIMABTEXBROWSE, &G.sima->menunr, do_global_buttons); + break; + } + else if(G.sima->menunr < 0) break; + + if(brush_texture_set_nr(brush, G.sima->menunr)) { + BIF_undo_push("Browse Brush Texture"); + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWIMAGE, 0); + } + } + break; + case B_SIMABTEXDELETE: + if(settings->imapaint.brush) { + if (brush_texture_delete(settings->imapaint.brush)) { + BIF_undo_push("Unlink Brush Texture"); + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWIMAGE, 0); + } + } + break; + case B_SIMA_PLAY: + play_anim(0); + break; + case B_SIMA_RECORD: + imagespace_composite_flipbook(curarea); + break; } } @@ -498,11 +672,19 @@ static void do_image_imagemenu(void *arg, int event) case 8: save_image_sima(); break; + case 9: + save_image_sequence_sima(); + break; + case 10: + BKE_image_memorypack(G.sima->image); + allqueue(REDRAWIMAGE, 0); + break; } } static uiBlock *image_imagemenu(void *arg_unused) { + ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser); uiBlock *block; short yco= 0, menuwidth=150; BPyMenu *pym; @@ -519,8 +701,10 @@ static uiBlock *image_imagemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reload|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + if(G.sima->image->source==IMA_SRC_SEQUENCE) + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Changed Images", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); if (G.sima->image->packedfile) { @@ -528,7 +712,13 @@ static uiBlock *image_imagemenu(void *arg_unused) } else { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack Image", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); } - + + /* only for dirty && specific image types */ + if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + if( ELEM(G.sima->image->source, IMA_SRC_FILE, IMA_SRC_GENERATED)) + if(G.sima->image->type!=IMA_TYPE_MULTILAYER) + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack Image as PNG", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=7, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); if(G.sima->flag & SI_DRAWTOOL) { @@ -877,12 +1067,13 @@ static uiBlock *image_uvsmenu(void *arg_unused) void image_buttons(void) { + Image *ima= G.sima->image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); uiBlock *block; short xco, xmax; char naam[256], *menuname; /* This should not be a static var */ static int headerbuttons_packdummy; - Image *ima= G.sima->image; headerbuttons_packdummy = 0; @@ -914,6 +1105,7 @@ void image_buttons(void) xco+=XIC; if((curarea->flag & HEADER_NO_PULLDOWN)==0) { + /* pull down menus */ uiBlockSetEmboss(block, UI_EMBOSSP); @@ -927,7 +1119,7 @@ void image_buttons(void) xco+= xmax; } - if (ima && ima->ibuf && (ima->ibuf->userflags & IB_BITMAPDIRTY)) + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) menuname= "Image*"; else menuname= "Image"; @@ -948,29 +1140,57 @@ void image_buttons(void) xco= std_libbuttons(block, xco, 0, 0, NULL, B_SIMABROWSE, ID_IM, 0, (ID *)ima, 0, &(G.sima->imanr), 0, 0, B_IMAGEDELETE, 0, 0); if (ima) { + RenderResult *rr= BKE_image_get_renderresult(ima); + xco+= 8; - if (ima->packedfile) { - headerbuttons_packdummy = 1; + if(rr) { + uiBlockBeginAlign(block); + uiblock_layer_pass_buttons(block, rr, &G.sima->iuser, B_REDR, xco, 0, 160); + uiBlockEndAlign(block); + xco+= 166; } - uiDefIconButBitI(block, TOG, 1, B_SIMAPACKIMA, ICON_PACKAGE, xco,0,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image"); - xco+= XIC+8; + if( !ELEM3(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_VIEWER) && ima->ok) { + if (ima->packedfile) { + headerbuttons_packdummy = 1; + } + if (ima->packedfile && (ibuf->userflags & IB_BITMAPDIRTY)) + uiDefIconButBitI(block, TOG, 1, B_SIMA_REPACK, ICON_UGLYPACKAGE, xco,0,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Re-Pack this image as PNG"); + else + uiDefIconButBitI(block, TOG, 1, B_SIMAPACKIMA, ICON_PACKAGE, xco,0,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image"); + + xco+= XIC+8; + } + uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button"); xco+= XIC+8; uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOG, SI_USE_ALPHA, B_SIMA_USE_ALPHA, ICON_TRANSP_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws image with alpha"); - xco+= XIC; - uiDefIconButBitI(block, TOG, SI_SHOW_ALPHA, B_SIMA_SHOW_ALPHA, ICON_DOT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws only alpha"); - xco+= XIC; - if(ima->ibuf) { - if(ima->ibuf->zbuf || ima->ibuf->zbuf_float) { + if(ibuf==NULL || ibuf->channels==4) { + uiDefIconButBitI(block, TOG, SI_USE_ALPHA, B_SIMA_USE_ALPHA, ICON_TRANSP_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws image with alpha"); + xco+= XIC; + uiDefIconButBitI(block, TOG, SI_SHOW_ALPHA, B_SIMA_SHOW_ALPHA, ICON_DOT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws only alpha"); + xco+= XIC; + } + if(ibuf) { + if(ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels==1)) { uiDefIconButBitI(block, TOG, SI_SHOW_ZBUF, B_SIMA_SHOW_ZBUF, ICON_SOLID, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws zbuffer values"); xco+= XIC; } else G.sima->flag &= ~SI_SHOW_ZBUF; /* no confusing display for non-zbuf images */ } + xco+= 8; + + uiBlockBeginAlign(block); + if(ima->type==IMA_TYPE_COMPOSITE) { + uiDefIconBut(block, BUT, B_SIMA_RECORD, ICON_REC, xco, 0, XIC, YIC, 0, 0, 0, 0, 0, "Record Composite"); + xco+= XIC; + } + if((ima->type==IMA_TYPE_COMPOSITE) || ELEM(G.sima->image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + uiDefIconBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, xco, 0, XIC, YIC, 0, 0, 0, 0, 0, "Play"); + xco+= XIC; + } uiBlockEndAlign(block); xco+= 8; } diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index d6c217534bb..03eed300520 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -529,15 +529,16 @@ static void check_packAll() // first check for dirty images Image *ima; - ima = G.main->image.first; - while (ima) { - if (ima->ibuf && (ima->ibuf->userflags &= IB_BITMAPDIRTY)) { - break; - } - ima= ima->id.next; + for(ima = G.main->image.first; ima; ima= ima->id.next) { + if (ima->ibufs.first) { /* XXX FIX */ + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if (ibuf && (ibuf->userflags &= IB_BITMAPDIRTY)) + break; } + } - if (ima == 0 || okee("Some images are painted on. These changes will be lost. Continue ?")) { + if (ima == NULL || okee("Some images are painted on. These changes will be lost. Continue ?")) { packAll(); G.fileflags |= G_AUTOPACK; } @@ -852,7 +853,7 @@ static void do_info_filemenu(void *arg, int event) } break; case 6: /* save image */ - BIF_save_rendered_image_fs(0); + BIF_save_rendered_image_fs(); break; case 22: /* save runtime */ activate_fileselect(FILE_SPECIAL, "Save Runtime", "", write_runtime_check); diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index a873f779b34..f32dbf0e760 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -490,6 +490,9 @@ static void do_node_nodemenu(void *arg, int event) case 9: /* show cyclic */ ntreeSolveOrder(snode->edittree); break; + case 10: /* execute */ + addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); + break; } if(fromlib==-1) error("Can't edit Library Data"); @@ -525,8 +528,10 @@ static uiBlock *node_nodemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - if(snode->treetype==NTREE_COMPOSIT) + if(snode->treetype==NTREE_COMPOSIT) { + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); + } uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Cyclic Dependencies|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); if(curarea->headertype==HEADERTOP) { diff --git a/source/blender/src/header_time.c b/source/blender/src/header_time.c index c018812e38b..968a34d1dbc 100644 --- a/source/blender/src/header_time.c +++ b/source/blender/src/header_time.c @@ -154,6 +154,10 @@ static uiBlock *time_redrawmenu(void *arg_unused) else icon= ICON_CHECKBOX_DEHLT; uiDefIconTextBut(block, BUTM, 1, icon, "Buttons Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_BUTS_WIN, ""); + if(stime->redraws & TIME_ALL_IMAGE_WIN) icon= ICON_CHECKBOX_HLT; + else icon= ICON_CHECKBOX_DEHLT; + uiDefIconTextBut(block, BUTM, 1, icon, "Image Windows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_ALL_IMAGE_WIN, ""); + /* Add sequencer only redraw*/ if(stime->redraws & TIME_SEQ) icon= ICON_CHECKBOX_HLT; else icon= ICON_CHECKBOX_DEHLT; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 1837ae2e384..7b283427492 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -279,6 +279,8 @@ int std_libbuttons(uiBlock *block, short xco, short yco, if (lb) { if( id_code==ID_IP) IPOnames_to_pupstring(&str, NULL, extrastr, lb, id, menupoin, G.sipo->blocktype); + else if(browse!=B_SIMABROWSE && id_code==ID_IM ) + IMAnames_to_pupstring(&str, NULL, extrastr, lb, id, menupoin); else IDnames_to_pupstring(&str, NULL, extrastr, lb, id, menupoin); } @@ -411,9 +413,12 @@ static void do_update_for_newframe(int mute, int events) /* this function applies the changes too */ scene_update_for_newframe(G.scene, screen_view3d_layers()); /* BKE_scene.h */ - if ( (CFRA>1) && (!mute) && (G.scene->audio.flag & AUDIO_SCRUB)) audiostream_scrub( CFRA ); + if ( (CFRA>1) && (!mute) && (G.scene->audio.flag & AUDIO_SCRUB)) + audiostream_scrub( CFRA ); + BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); + BIF_image_update_frame(); } void update_for_newframe(void) @@ -573,7 +578,7 @@ void do_global_buttons(unsigned short event) ScrArea *sa; Brush *br; int nr= 1; - char buf[FILE_MAXDIR+FILE_MAXFILE]; + char buf[FILE_MAX]; ob= OBACT; @@ -1518,8 +1523,8 @@ void do_global_buttons(unsigned short event) allqueue(REDRAWNLA, 1); /* name scene also in set PUPmenu */ allqueue(REDRAWBUTSALL, 0); + allqueue(REDRAWIMAGE, 0); allqueue(REDRAWHEADERS, 0); - break; case B_KEEPDATA: diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 21573ba0a11..3724aaf43a0 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -56,6 +56,7 @@ #include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -65,7 +66,9 @@ #include "BKE_brush.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_mesh.h" +#include "BKE_node.h" #include "BKE_utildefines.h" #include "BIF_mywindow.h" @@ -74,6 +77,7 @@ #include "BIF_toolbox.h" #include "BSE_drawipo.h" +#include "BSE_node.h" #include "BSE_trans_types.h" #include "BSE_view.h" @@ -84,6 +88,7 @@ #include "GHOST_Types.h" #include "blendef.h" +#include "butspace.h" #include "mydevice.h" /* Defines and Structs */ @@ -109,6 +114,7 @@ typedef struct ImagePaintState { ImBuf *clonecanvas; short clonefreefloat; char *warnpackedfile; + char *warnmultifile; /* texture paint only */ Object *ob; @@ -132,21 +138,21 @@ typedef struct ImagePaintPartialRedraw { static ImagePaintUndo imapaintundo = {NULL, NULL, NULL, 0, 0}; static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; -static void init_imagapaint_undo(Image *ima) +static void init_imagapaint_undo(Image *ima, ImBuf *ibuf) { int xt, yt; imapaintundo.image = ima; - imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ima->ibuf->x); - imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ima->ibuf->y); + imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ibuf->x); + imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ibuf->y); imapaintundo.tiles = MEM_callocN(sizeof(void*)*xt*yt, "ImagePaintUndoTiles"); imapaintundo.tilebuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, - ima->ibuf->depth, (ima->ibuf->rect_float)? IB_rectfloat: IB_rect, 0); + ibuf->depth, (ibuf->rect_float)? IB_rectfloat: IB_rect, 0); } -static void imapaint_copy_tile(Image *ima, int tile, int x, int y, int swapundo) +static void imapaint_copy_tile(ImBuf *ibuf, int tile, int x, int y, int swapundo) { - IMB_rectcpy(imapaintundo.tilebuf, ima->ibuf, 0, 0, x*IMAPAINT_TILE_SIZE, + IMB_rectcpy(imapaintundo.tilebuf, ibuf, 0, 0, x*IMAPAINT_TILE_SIZE, y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); if (imapaintundo.tilebuf->rect_float) @@ -155,7 +161,7 @@ static void imapaint_copy_tile(Image *ima, int tile, int x, int y, int swapundo) SWAP(void*, imapaintundo.tilebuf->rect, imapaintundo.tiles[tile]) if (swapundo) - IMB_rectcpy(ima->ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE, + IMB_rectcpy(ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE, y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } @@ -164,11 +170,11 @@ static void imapaint_clear_partial_redraw() memset(&imapaintpartial, 0, sizeof(imapaintpartial)); } -static void imapaint_dirty_region(Image *ima, int x, int y, int w, int h) +static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { int srcx= 0, srcy= 0, origx, tile, allocsize; - IMB_rectclip(ima->ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); + IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); if (w == 0 || h == 0) return; @@ -196,27 +202,29 @@ static void imapaint_dirty_region(Image *ima, int x, int y, int w, int h) for (x=origx; x <= w; x++) { if (ima != imapaintundo.image) { free_imagepaint(); - init_imagapaint_undo(ima); + init_imagapaint_undo(ima, ibuf); } tile = y*imapaintundo.xtiles + x; if (!imapaintundo.tiles[tile]) { - allocsize= (ima->ibuf->rect_float)? sizeof(float): sizeof(char); + allocsize= (ibuf->rect_float)? sizeof(float): sizeof(char); imapaintundo.tiles[tile]= MEM_mapallocN(allocsize*4* IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE, "ImagePaintUndoTile"); - imapaint_copy_tile(ima, tile, x, y, 0); + imapaint_copy_tile(ibuf, tile, x, y, 0); } } } - ima->ibuf->userflags |= IB_BITMAPDIRTY; + ibuf->userflags |= IB_BITMAPDIRTY; } -static void imapaint_image_update(Image *image, short texpaint) +static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) { - if(image->ibuf->rect_float) - imb_freerectImBuf(image->ibuf); /* force recreate of char rect */ - + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* force recreate of char rect */ + if(ibuf->mipmap[0]) + imb_freemipmapImBuf(ibuf); + /* todo: should set_tpage create ->rect? */ if(texpaint || G.sima->lock) { int w = imapaintpartial.x2 - imapaintpartial.x1; @@ -236,6 +244,24 @@ static void imapaint_redraw(int final, int texpaint, Image *image) allqueue(REDRAWVIEW3D, 0); } allqueue(REDRAWHEADERS, 0); + + /* after paint, tag Image or RenderResult nodes changed */ + if(G.scene->nodetree) { + imagepaint_composite_tags(G.scene->nodetree, image, &G.sima->iuser); + } + /* signal composite (hurmf, need an allqueue?) */ + if(G.sima->lock) { + ScrArea *sa; + for(sa=G.curscreen->areabase.first; sa; sa= sa->next) { + if(sa->spacetype==SPACE_NODE) { + if(((SpaceNode *)sa->spacedata.first)->treetype==NTREE_COMPOSIT) { + addqueue(sa->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); + break; + } + } + } + } + } else if(!texpaint && G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0); @@ -245,20 +271,21 @@ static void imapaint_redraw(int final, int texpaint, Image *image) void imagepaint_undo() { - int x, y, tile; Image *ima= imapaintundo.image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); + int x, y, tile; - if (!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) return; for (tile = 0, y = 0; y < imapaintundo.ytiles; y++) for (x = 0; x < imapaintundo.xtiles; x++, tile++) if (imapaintundo.tiles[tile]) - imapaint_copy_tile(ima, tile, x, y, 1); + imapaint_copy_tile(ibuf, tile, x, y, 1); free_realtime_image(ima); /* force OpenGL reload */ - if(ima->ibuf->rect_float) - imb_freerectImBuf(ima->ibuf); /* force recreate of char rect */ + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* force recreate of char rect */ allqueue(REDRAWIMAGE, 0); allqueue(REDRAWVIEW3D, 0); @@ -435,7 +462,7 @@ static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *p clonebuf= imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos); } - imapaint_dirty_region(s->image, bpos[0], bpos[1], ibufb->x, ibufb->y); + imapaint_dirty_region(s->image, s->canvas, bpos[0], bpos[1], ibufb->x, ibufb->y); /* blend into canvas */ if(torus) @@ -479,26 +506,32 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float static int imapaint_canvas_set(ImagePaintState *s, Image *ima) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); + /* verify that we can paint and set canvas */ - if(ima->packedfile) { + if(ima->packedfile && ima->rr) { s->warnpackedfile = ima->id.name + 2; return 0; - } - else if(!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float)) + } + else if(ibuf && ibuf->channels!=4) { + s->warnmultifile = ima->id.name + 2; return 0; - else if(ima->packedfile) + } + else if(!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) return 0; s->image= ima; - s->canvas= ima->ibuf; + s->canvas= ibuf; /* set clone canvas */ if(s->tool == PAINT_TOOL_CLONE) { ima= s->brush->clone.image; - if(!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float)) + ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser); + + if(!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) return 0; - s->clonecanvas= ima->ibuf; + s->clonecanvas= ibuf; if(s->canvas->rect_float && !s->clonecanvas->rect_float) { /* temporarily add float rect for cloning */ @@ -520,16 +553,17 @@ static void imapaint_canvas_free(ImagePaintState *s) static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) { + ImBuf *ibuf= BKE_image_get_ibuf(image, &G.sima->iuser); float pos[2]; - pos[0] = uv[0]*image->ibuf->x; - pos[1] = uv[1]*image->ibuf->y; + pos[0] = uv[0]*ibuf->x; + pos[1] = uv[1]*ibuf->y; - brush_painter_require_imbuf(painter, ((image->ibuf->rect_float)? 1: 0), 0, 0); + brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0); if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s)) { if (update) - imapaint_image_update(image, texpaint); + imapaint_image_update(image, ibuf, texpaint); return 1; } else return 0; @@ -546,8 +580,12 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho /* pick new face and image */ if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) { + ImBuf *ibuf; + newimage = (Image*)((s->me->mtface+newfaceindex)->tpage); - if(newimage && newimage->ibuf && newimage->ibuf->rect) + ibuf= BKE_image_get_ibuf(newimage, &G.sima->iuser); + + if(ibuf && ibuf->rect) texpaint_pick_uv(s->ob, s->me, newfaceindex, mval, newuv); else newimage = NULL; @@ -641,8 +679,10 @@ void imagepaint_paint(short mousebutton, short texpaint) s.image = G.sima->image; if(!imapaint_canvas_set(&s, G.sima->image)) { + if(s.warnmultifile) + error("Image requires 4 color channels to paint"); if(s.warnpackedfile) - error("Painting in packed images not supported"); + error("Packed MultiLayer files cannot be painted"); return; } } @@ -694,9 +734,12 @@ void imagepaint_paint(short mousebutton, short texpaint) imapaint_redraw(1, texpaint, s.image); + if (texpaint) { - if (s.warnpackedfile) - error("Painting in packed images is not supported: %s", s.warnpackedfile); + if (s.warnmultifile) + error("Image requires 4 color channels to paint: %s", s.warnmultifile); + if(s.warnpackedfile) + error("Packed MultiLayer files cannot be painted %s", s.warnpackedfile); persp(PERSP_WIN); } @@ -708,7 +751,7 @@ void imagepaint_pick(short mousebutton) Brush *brush= settings->imapaint.brush; if(brush && (settings->imapaint.tool == PAINT_TOOL_CLONE)) { - if(brush->clone.image && brush->clone.image->ibuf) { + if(brush->clone.image) { short prevmval[2], mval[2]; float lastmousepos[2], mousepos[2]; diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 13b72739d0d..9eb68578968 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -118,8 +118,10 @@ float UIwinmat[4][4]; static int UIlock= 0, UIafterval; static char *UIlockstr=NULL; -static void (*UIafterfunc)(void *arg, int event); -static void *UIafterfunc_arg; + +static void (*UIafterfunc_butm)(void *arg, int event); +static void (*UIafterfunc_but)(void *arg1, void *arg2); +static void *UIafterfunc_arg1, *UIafterfunc_arg2; static uiFont UIfont[UI_ARRAY]; // no init needed uiBut *UIbuttip; @@ -1481,7 +1483,10 @@ static int ui_do_but_BUT(uiBut *but) activated= (but->flag & UI_SELECT); if(activated) { - uibut_do_func(but); + UIafterfunc_but= but->func; + UIafterfunc_arg1= but->func_arg1; + UIafterfunc_arg2= but->func_arg2; + /* no more uibut_do_func(but); this button calls fileselecting windows */ } but->flag &= ~UI_SELECT; @@ -2649,8 +2654,8 @@ static int ui_do_but_BUTM(uiBut *but) { ui_set_but_val(but, but->min); - UIafterfunc= but->butm_func; - UIafterfunc_arg= but->butm_func_arg; + UIafterfunc_butm= but->butm_func; + UIafterfunc_arg1= but->butm_func_arg; UIafterval= but->a2; return but->retval; @@ -4899,7 +4904,9 @@ int uiDoBlocks(ListBase *lb, int event) if(event==MOUSEX) return UI_NOTHING; UIbuttip= NULL; - UIafterfunc= NULL; /* to prevent infinite loops, this shouldnt be a global! */ + UIafterfunc_butm= NULL; /* to prevent infinite loops, this shouldnt be a global! */ + UIafterfunc_but= NULL; /* to prevent infinite loops, this shouldnt be a global! */ + UIafterfunc_arg1= UIafterfunc_arg2= NULL; uevent.qual= G.qual; uevent.event= event; @@ -5016,11 +5023,16 @@ int uiDoBlocks(ListBase *lb, int event) /* afterfunc is used for fileloading too, so after this call, the blocks pointers are invalid */ if(retval & UI_RETURN_OK) { - if(UIafterfunc) { + if(UIafterfunc_butm) { + mywinset(curarea->win); + UIafterfunc_butm(UIafterfunc_arg1, UIafterval); + UIafterfunc_butm= NULL; + } + if(UIafterfunc_but) { mywinset(curarea->win); - UIafterfunc(UIafterfunc_arg, UIafterval); + UIafterfunc_but(UIafterfunc_arg1, UIafterfunc_arg2); + UIafterfunc_but= NULL; } - UIafterfunc= NULL; } /* tooltip */ diff --git a/source/blender/src/interface_icons.c b/source/blender/src/interface_icons.c index 3fb6caf15b5..568907c77e7 100644 --- a/source/blender/src/interface_icons.c +++ b/source/blender/src/interface_icons.c @@ -699,10 +699,12 @@ static void icon_from_image(Image *img, RenderInfo *ri) /* new rule: never read images, so icons get created while user works, not always on first use of a menu */ if(!img->preview) { - if(img->ibuf==NULL || img->ibuf->rect==NULL) { + ImBuf *ibuf; + if(img->ok!=IMA_OK_LOADED) { return; } - icon_copy_rect(img->ibuf, ri); + ibuf= BKE_image_get_ibuf(img, NULL); + icon_copy_rect(ibuf, ri); /* now copy the created preview to the DNA struct to be saved in file */ img->preview = MEM_callocN(sizeof(PreviewImage), "img_prv"); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 1a97a3d594f..2d2ea2c8e0c 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -70,6 +70,7 @@ void sort_faces(void); #include "BKE_depsgraph.h" #include "BKE_customdata.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -850,10 +851,13 @@ void objects_bake_render(void) else { Image *ima; /* force OpenGL reload */ - for(ima= G.main->image.first; ima; ima= ima->id.next) - if(ima->ibuf) - if(ima->ibuf->userflags & IB_BITMAPDIRTY) + for(ima= G.main->image.first; ima; ima= ima->id.next) { + if(ima->ok==IMA_OK_LOADED) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) free_realtime_image(ima); + } + } } allqueue(REDRAWIMAGE, 0); diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index a6e0d2ef27e..5113e261fa5 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -269,6 +269,8 @@ static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_ /* set world always back, is used now */ sce->world= pr_main->world.first; + sce->r.cfra= G.scene->r.cfra; + if(id_type==ID_MA) { Material *mat= (Material *)id; diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index f6bd1d76524..bba8a9ebb45 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -599,7 +599,7 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val mainwindow_make_active(); rw->active= 0; areawinset(find_biggest_area()->win); - BIF_save_rendered_image_fs(0); + BIF_save_rendered_image_fs(); } } else if (evt==F11KEY) { @@ -1115,17 +1115,20 @@ static void do_render(int anim) waitcursor(0); } +/* called before render, store old render in spare buffer */ static void renderwin_store_spare(void) { RenderResult rres; if(render_win==0 || render_win->storespare==0) return; - - if(render_win->showspare) { - render_win->showspare= 0; - window_set_title(render_win->win, renderwin_get_title(1)); - } + + /* only store when it does not show spare */ + if(render_win->showspare==0) + return; + + render_win->showspare= 0; + window_set_title(render_win->win, renderwin_get_title(1)); BLI_strncpy(render_win->render_text_spare, render_win->render_text, RW_MAXTEXT); @@ -1197,6 +1200,14 @@ void BIF_end_render_callbacks(void) } } +void BIF_store_spare(void) +{ + if(render_win) + renderwin_store_spare(); + else + imagewin_store_spare(); +} + /* set up display, render an image or scene */ void BIF_do_render(int anim) { @@ -1210,8 +1221,7 @@ void BIF_do_render(int anim) } } - if(render_win && render_win->showspare) - renderwin_store_spare(); + BIF_store_spare(); do_render(anim); @@ -1327,12 +1337,7 @@ void BIF_redraw_render_rect(void) renderwin_queue_redraw(render_win); } else { - Image *ima = (Image *)find_id("IM", "Render Result"); - if(ima && ima->ibuf) { - IMB_freeImBuf(ima->ibuf); - ima->ibuf= NULL; - allqueue(REDRAWIMAGE, 0); - } + allqueue(REDRAWIMAGE, 0); } } @@ -1340,22 +1345,26 @@ void BIF_swap_render_rects(void) { RenderResult rres; - if (render_win==NULL) return; - - render_win->storespare= 1; - render_win->showspare ^= 1; + if(G.displaymode!=R_DISPLAYWIN) { + imagewindow_swap_render_rects(); + } + else { - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + render_win->storespare= 1; + render_win->showspare ^= 1; + + RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + + if(render_win->sparex!=rres.rectx || render_win->sparey!=rres.recty) { + if(render_win->rectspare) MEM_freeN(render_win->rectspare); + render_win->rectspare= NULL; + if(render_win->rectsparef) MEM_freeN(render_win->rectsparef); + render_win->rectsparef= NULL; + } - if(render_win->sparex!=rres.rectx || render_win->sparey!=rres.recty) { - if(render_win->rectspare) MEM_freeN(render_win->rectspare); - render_win->rectspare= NULL; - if(render_win->rectsparef) MEM_freeN(render_win->rectsparef); - render_win->rectsparef= NULL; + window_set_title(render_win->win, renderwin_get_title(1)); } - window_set_title(render_win->win, renderwin_get_title(1)); - /* redraw */ BIF_redraw_render_rect(); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index af6a5043244..a9de9e01ea8 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -4347,7 +4347,7 @@ static void init_imaselspace(ScrArea *sa) simasel->firstdir = 0; simasel->firstfile = 0; simasel->cmap = 0; - simasel->returnfunc = 0; + simasel->returnfunc = NULL; simasel->title[0] = 0; @@ -4589,7 +4589,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) /* Events handled always (whether the draw tool is active or not) */ switch (event) { case UI_BUT_EVENT: - do_imagebuts(val); /* drawimage.c */ + do_image_buttons(val); /* header_image.c */ break; case MIDDLEMOUSE: if((G.qual==LR_CTRLKEY) || ((U.flag & USER_TWOBUTTONMOUSE) && (G.qual==(LR_ALTKEY|LR_CTRLKEY)))) @@ -4665,6 +4665,10 @@ static void init_imagespace(ScrArea *sa) sima->zoom= 1; sima->blockscale= 0.7; sima->flag = SI_LOCALSTICKY; + + sima->iuser.ok= 1; + sima->iuser.fie_ima= 2; + sima->iuser.frames= 100; } @@ -5216,14 +5220,14 @@ void newspace(ScrArea *sa, int type) sfile->type= FILE_UNIX; } - sfile->returnfunc= 0; + sfile->returnfunc= NULL; sfile->title[0]= 0; if(sfile->filelist) test_flags_file(sfile); } /* exception: imasel space */ else if(sa->spacetype==SPACE_IMASEL) { SpaceImaSel *simasel= sa->spacedata.first; - simasel->returnfunc= 0; + simasel->returnfunc= NULL; simasel->title[0]= 0; } else if(sa->spacetype==SPACE_OOPS) { @@ -5248,6 +5252,8 @@ void freespacelist(ScrArea *sa) BLO_blendhandle_close(sfile->libfiledata); if(sfile->filelist) freefilelist(sfile); + if(sfile->pupmenu) + MEM_freeN(sfile->pupmenu); } else if(sl->spacetype==SPACE_BUTS) { SpaceButs *buts= (SpaceButs*) sl; @@ -5266,7 +5272,6 @@ void freespacelist(ScrArea *sa) else if(sl->spacetype==SPACE_VIEW3D) { View3D *vd= (View3D*) sl; if(vd->bgpic) { - if(vd->bgpic->rect) MEM_freeN(vd->bgpic->rect); if(vd->bgpic->ima) vd->bgpic->ima->id.us--; MEM_freeN(vd->bgpic); } @@ -5312,6 +5317,10 @@ void freespacelist(ScrArea *sa) curvemapping_free(sima->cumap); if(sima->info_str) MEM_freeN(sima->info_str); + if(sima->info_spare) + MEM_freeN(sima->info_spare); + if(sima->spare) + IMB_freeImBuf(sima->spare); } else if(sl->spacetype==SPACE_NODE) { /* SpaceNode *snode= (SpaceNode *)sl; */ @@ -5321,6 +5330,7 @@ void freespacelist(ScrArea *sa) BLI_freelistN(&sa->spacedata); } +/* can be called for area-full, so it should keep interesting stuff */ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) { SpaceLink *sl; @@ -5333,8 +5343,10 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) while(sl) { if(sl->spacetype==SPACE_FILE) { SpaceFile *sfile= (SpaceFile*) sl; - sfile->libfiledata= 0; - sfile->filelist= 0; + sfile->libfiledata= NULL; + sfile->filelist= NULL; + sfile->pupmenu= NULL; + sfile->menup= NULL; } else if(sl->spacetype==SPACE_VIEW3D) { View3D *v3d= (View3D*)sl; @@ -5351,6 +5363,10 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) else if(sl->spacetype==SPACE_IMASEL) { check_imasel_copy((SpaceImaSel *) sl); } + else if(sl->spacetype==SPACE_IMAGE) { + SpaceImage *sima= (SpaceImage *)sl; + sima->spare= NULL; + } else if(sl->spacetype==SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; snode->nodetree= NULL; @@ -5359,6 +5375,8 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) sl= sl->next; } + /* but some things we copy */ + sl= lb1->first; while(sl) { sl->area= newarea; @@ -5367,6 +5385,10 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) SpaceButs *buts= (SpaceButs *)sl; buts->ri= NULL; } + else if(sl->spacetype==SPACE_FILE) { + SpaceFile *sfile= (SpaceFile*) sl; + sfile->menup= NULL; + } else if(sl->spacetype==SPACE_IPO) { SpaceIpo *si= (SpaceIpo *)sl; si->editipo= NULL; @@ -5376,7 +5398,6 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) View3D *vd= (View3D *)sl; if(vd->bgpic) { vd->bgpic= MEM_dupallocN(vd->bgpic); - vd->bgpic->rect= NULL; if(vd->bgpic->ima) vd->bgpic->ima->id.us++; } vd->clipbb= MEM_dupallocN(vd->clipbb); @@ -5389,6 +5410,8 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) sima->cumap= curvemapping_copy(sima->cumap); if(sima->info_str) sima->info_str= MEM_dupallocN(sima->info_str); + if(sima->info_spare) + sima->info_spare= MEM_dupallocN(sima->info_spare); } sl= sl->next; } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index f5b9ccf3f81..51c54cf6661 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -456,15 +456,12 @@ int blenderqread(unsigned short event, short val) break; case F3KEY: if(G.qual==0) { - BIF_save_rendered_image_fs(0); + BIF_save_rendered_image_fs(); return 0; } else if(G.qual & LR_CTRLKEY) { BIF_screendump(0); } - else if(G.qual & LR_SHIFTKEY) { - BIF_save_rendered_image_fs(1); - } break; case F4KEY: if(G.qual==LR_SHIFTKEY) { @@ -473,7 +470,7 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(ob) strcpy(str, ob->id.name); - activate_fileselect(FILE_MAIN, "Data Select", str, 0); + activate_fileselect(FILE_MAIN, "Data Select", str, NULL); return 0; } else if(G.qual==0) { diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 4601fa77b3a..c9fced04a00 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -74,6 +74,7 @@ #include "BKE_displist.h" #include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_library.h" #include "BKE_mesh.h" #include "BKE_node.h" @@ -709,9 +710,7 @@ void replace_names_but(void) strcat(temp, ima->name+len); BLI_strncpy(ima->name, temp, sizeof(ima->name)); - if(ima->ibuf) IMB_freeImBuf(ima->ibuf); - ima->ibuf= 0; - ima->ok= 1; + BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); tot++; } diff --git a/source/blender/src/verse_object.c b/source/blender/src/verse_object.c index 2a285d828b9..572849b5a92 100644 --- a/source/blender/src/verse_object.c +++ b/source/blender/src/verse_object.c @@ -289,7 +289,7 @@ void b_verse_pop_node(VNode *vnode) return; } - vbitmap->image = (void*)new_image( + vbitmap->image = (void*)BKE_add_image_size( vbitmap->width, vbitmap->height, vnode->name, diff --git a/source/blender/src/writeimage.c b/source/blender/src/writeimage.c index 6d167d858ff..530d0535baa 100644 --- a/source/blender/src/writeimage.c +++ b/source/blender/src/writeimage.c @@ -66,17 +66,17 @@ void BIF_save_envmap(EnvMap *env, char *str) int dx; /* all interactive stuff is handled in buttons.c */ - if(env->cube[0]==NULL || env->cube[0]->ibuf==NULL) return; + if(env->cube[0]==NULL) return; - dx= env->cube[0]->ibuf->x; + dx= env->cube[0]->x; ibuf= IMB_allocImBuf(3*dx, 2*dx, 24, IB_rect, 0); - IMB_rectcpy(ibuf, env->cube[0]->ibuf, 0, 0, 0, 0, dx, dx); - IMB_rectcpy(ibuf, env->cube[1]->ibuf, dx, 0, 0, 0, dx, dx); - IMB_rectcpy(ibuf, env->cube[2]->ibuf, 2*dx, 0, 0, 0, dx, dx); - IMB_rectcpy(ibuf, env->cube[3]->ibuf, 0, dx, 0, 0, dx, dx); - IMB_rectcpy(ibuf, env->cube[4]->ibuf, dx, dx, 0, 0, dx, dx); - IMB_rectcpy(ibuf, env->cube[5]->ibuf, 2*dx, dx, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[0], 0, 0, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[1], dx, 0, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[2], 2*dx, 0, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[3], 0, dx, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[4], dx, dx, 0, 0, dx, dx); + IMB_rectcpy(ibuf, env->cube[5], 2*dx, dx, 0, 0, dx, dx); BKE_write_ibuf(ibuf, str, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality); IMB_freeImBuf(ibuf); @@ -86,12 +86,10 @@ void BIF_save_envmap(EnvMap *env, char *str) #define FTOCHAR(val) val<=0.0f?255: 255-(val>=255.0f?255: (char)(val)) /* callback for fileselect to save rendered image, renderresult was checked to exist */ -void save_rendered_image_cb_real(char *name, int zbuf, int confirm) +static void save_rendered_image_cb_real(char *name, int confirm) { char str[FILE_MAXDIR+FILE_MAXFILE]; - int pixel, end, overwrite; - float *pixf = 0; - char *pixc = 0; + int overwrite; if(BLI_testextensie(name,".blend")) { error("Wrong filename"); @@ -112,54 +110,37 @@ void save_rendered_image_cb_real(char *name, int zbuf, int confirm) overwrite = 1; if(overwrite) { - RenderResult rres; - ImBuf *ibuf; - - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); - - waitcursor(1); /* from screen.c */ - - ibuf= IMB_allocImBuf(rres.rectx, rres.recty, G.scene->r.planes, 0, 0); - if (zbuf == 1) { - if (ibuf->rect ==NULL) imb_addrectImBuf(ibuf); - if (ibuf->rect_float==NULL) imb_addrectfloatImBuf(ibuf); - - ibuf->zbuf_float= rres.rectz; + if(G.scene->r.imtype==R_MULTILAYER) { + RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); + if(rr) + RE_WriteRenderResult(rr, str); + } + else { + RenderResult rres; + ImBuf *ibuf; + + RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); - pixc = (char *)ibuf->rect; - pixf = (float *)ibuf->rect_float; + waitcursor(1); /* from screen.c */ - end = ibuf->x * ibuf->y; - for(pixel = 0; pixel < end; pixel++, pixf+=4, pixc+=4) { - pixf[0] = pixf[1] = pixf[2] = pixf[3] = 1-rres.rectz[pixel]/100000000000.0; - pixc[0] = pixc[1] = pixc[2] = pixc[3] = FTOCHAR(rres.rectz[pixel]); - } - ibuf->zbuf_float= rres.rectz; - } else { + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, G.scene->r.planes, 0, 0); ibuf->rect= rres.rect32; ibuf->rect_float= rres.rectf; ibuf->zbuf_float= rres.rectz; + + /* float factor for random dither, imbuf takes care of it */ + ibuf->dither= G.scene->r.dither_intensity; + + BKE_write_ibuf(ibuf, str, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality); + IMB_freeImBuf(ibuf); /* imbuf knows rects are not part of ibuf */ } - /* float factor for random dither, imbuf takes care of it */ - ibuf->dither= G.scene->r.dither_intensity; - - BKE_write_ibuf(ibuf, str, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality); - IMB_freeImBuf(ibuf); /* imbuf knows rects are not part of ibuf */ - strcpy(G.ima, name); waitcursor(0); } } -static void save_rendered_image_cb(char *name) { - save_rendered_image_cb_real(name,0,1); -} - -static void save_rendered_image_zbuf_cb(char *name) { - save_rendered_image_cb_real(name,1,1); -} void save_image_filesel_str(char *str) { @@ -203,7 +184,9 @@ void save_image_filesel_str(char *str) case R_TARGA: strcpy(str, "Save Targa"); break; - + case R_MULTILAYER: + strcpy(str, "Save Multi Layer EXR"); + break; /* default we save jpeg, also for all movie formats */ case R_JPEG90: case R_MOVIE: @@ -216,8 +199,19 @@ void save_image_filesel_str(char *str) } } -/* calls fileselect if zbuf is set we are rendering the zbuffer */ -void BIF_save_rendered_image_fs(int zbuf) +static void save_rendered_image_cb(char *name) +{ + save_rendered_image_cb_real(name, 1); +} + +/* no fileselect, no confirm */ +void BIF_save_rendered_image(char *name) +{ + save_rendered_image_cb_real(name, 0); +} + +/* calls fileselect */ +void BIF_save_rendered_image_fs(void) { RenderResult rres; @@ -225,7 +219,8 @@ void BIF_save_rendered_image_fs(int zbuf) if(!rres.rectf && !rres.rect32) { error("No image rendered"); - } else { + } + else { char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2]; if(G.ima[0]==0) { @@ -235,10 +230,6 @@ void BIF_save_rendered_image_fs(int zbuf) } save_image_filesel_str(str); - if (zbuf) { - activate_fileselect(FILE_SPECIAL, str, G.ima, save_rendered_image_zbuf_cb); - return; - } activate_fileselect(FILE_SPECIAL, str, G.ima, save_rendered_image_cb); } } diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h index fa7afdbcbd9..0d794b6755d 100644 --- a/source/blender/yafray/intern/yafray_Render.h +++ b/source/blender/yafray/intern/yafray_Render.h @@ -22,7 +22,6 @@ extern "C" { #include "DNA_world_types.h" #include "BKE_global.h" -#include "BKE_image.h" #include "render_types.h" /* display_draw() needs render layer info */ -- cgit v1.2.3